【Spring源码解读一】IoC容器之AnnotationConfigApplicationContext

AnnotationConfigApplicationContext构造方法

this()

AnnotatedBeanDefinitionReader

ClassPathBeanDefinitionScanner

register(componentClasses)


        根据AnnotationConfigApplicationContext类去阅读其将Bean对象交给IoC容器管理的过程。以下这三个代码块是将配置类注册进IoC容器的例子。下面是关于这个类的继承与实现的类图关系树。

public class Test {
	public static void main(String[] args) {
		// 配置类注册进IoC容器
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
		User user = applicationContext.getBean(User.class);
		System.out.println(user.introduce("zhangSan",18));
	}
}
@Configuration
public class SpringConfig {

	@Bean
	public User user() {
		return new User();
	}
}
public class User {
	private String name;
	private Integer age;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public String introduce(String name, Integer age) {
		return "name:" + name + ",age:" + age;
	}
}

        首先在进入AnnotationConfigApplicationContext类中会先进入到其父类的静态代码块中,这个问题不大,不用刻意去在意。

static {
    // 避免急切的出现类加载器问题导致WebLogic 8.1中的应用程序关闭
    ContextClosedEvent.class.getName();
}

AnnotationConfigApplicationContext构造方法

        可以看到简简单单写了三个方法:this()、register(componentClasses)、refresh()。但在内部却有着十分多的代码量。这里先小小的记录以下这三个方法的作用:

1、this()方法是在AnnotatedBeanDefinitionReader中加载BeanDefinition,也就是Bean描述。还有在ClassPathBeanDefinitionScanner中扫描被@Component、@ManagedBean、@Named注解的类。

2、register()方法是将Bean描述包装成BeanDefinitionHolder再将其BeanDefinitionHolder中的Bean描述注册到Map<String, BeanDefinition> beanDefinitionMap中。

3、refresh()方法主要是刷新IoC容器的十二大步骤,其实也不止十二个步骤。

/**
 * 创建一个新的AnnotationConfigApplicationContext,从给定的组件类派生bean定义并自动刷新上下文。
 * @param componentClasses one or more component classes &mdash; for example,
 * {@link Configuration @Configuration} classes
 */
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
	this();
	register(componentClasses);
	refresh();
}

        这里需要注意的是在进入这个AnnotationConfigApplicationContext的this()无参构造时,由于此类AnnotationConfigApplicationContext继承了GenericApplicationContext,所以会先执行父类的无参构造方法。从以下代码可以看到创建了一个DefaultListableBeanFactory对象,这个对象将会在下面的unwrapDefaultListableBeanFactory中就有这个对象的判断。

public GenericApplicationContext() {
	this.beanFactory = new DefaultListableBeanFactory();
}

this()

        从这个方法调用另一个无参构造如下:一个是AnnotatedBeanDefinitionReader读取器与另一个ClassPathBeanDefinitionScanner扫描器。以下主要讲这两个中的作用。

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

	private final AnnotatedBeanDefinitionReader reader;

	private final ClassPathBeanDefinitionScanner scanner;

	public AnnotationConfigApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
    
    // 其它源码先省略
}

AnnotatedBeanDefinitionReader

         从下面源码可以看到从一个参数的有参构造方法中调用了另一个有两个参数的有参构造方法。从前面的源码中也可以知道传来的BeanDefinitionRegistry也就是AnnotationConfigApplicationContext类,那么第二个参数是用getOrCreateEnvironment()方法中获取到的,单从英语角度来说:可以猜测是创建一个环境,那么是什么环境呢,接着往里面看。

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
	this(registry, getOrCreateEnvironment(registry));
}

/**
 * 使用给定的{@link Environment}为给定的注册表创建新的{@code AnnotatedBeanDefinitionReader}
 */
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	Assert.notNull(environment, "Environment must not be null");
	this.registry = registry;
	this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
	AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

getOrCreateEnvironment(registry)

         从下面源码可以看到传来的这个BeanDefinitionRegistory去判断是否为EnvironmentCapable,如果是就返回这个环境,如果不是就返回一个标准环境。

private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	if (registry instanceof EnvironmentCapable) {
		return ((EnvironmentCapable) registry).getEnvironment();
	}
	return new StandardEnvironment();
}

new ConditionEvalator(register,environment,null)

        接下来再来看看第二个有参构造的这个ConditionEvalator类是做什么的。于是debug去查看。看完后我只能说 我看不懂。所以就先记录以下Spring配置的环境信息。大概是推断是传来的BeanDefinitionFactory是属于哪种BeanFactory,以及环境、资源加载器、类加载器属于哪种。

AnnotationConfigUtils.registerAnnotationConfigProcessors

        进入registerAnnotationConfigProcessors()这个方法中会调用本类的另一个重载方法,在这个重载方法中,第一个会进入到unwrapDefaultListableBeanFactory()方法,并且将BeanDefinfitionRegistry传进去。在这个registerAnnotationConfigProcessors()方法中主要是注册各种处理器。

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
	registerAnnotationConfigProcessors(registry, null);
}

/**
 * 在给定的注册表中注册所有相关的注释后处理程序。
 * @param registry 要操作的注册
 * @param source 配置源元素(已提取)
 * 触发此注册的。可能是{@code null}。
 * @return 一组BeanDefinitionHolders,包含此调用实际注册的所有bean定义
 */
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
		BeanDefinitionRegistry registry, @Nullable Object source) {

	DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
	if (beanFactory != null) {
		if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            // 注册了实现Order接口的排序器
			beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
		}
		if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            //设置@AutoWired的候选的解析器
			beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
		}
	}

    // 存放Bean描述(BeanDefinitionHolder)的包装
	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

	/**
	 * 注册解析我们配置类的后置处理器ConfigurationClassPostProcessor
	 * org.springframework.context.annotation.internalConfigurationAnnotationProcessor
	 */
	if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	/**
	 * 注册处理@Autowired 注解的处理器AutowiredAnnotationBeanPostProcessor
	 * org.springframework.context.annotation.internalAutowiredAnnotationProcessor
	 */
	if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	/**
	 * 注册处理JSR规范的注解处理器CommonAnnotationBeanPostProcessor
	 * org.springframework.context.annotation.internalCommonAnnotationProcessor
	 */
	// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
	if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	/**
	 * 处理jpa注解的处理器
	 * org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor
	 */
	// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
	if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition();
		try {
			def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
					AnnotationConfigUtils.class.getClassLoader()));
		}
		catch (ClassNotFoundException ex) {
			throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
		}
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	/**
	 * 处理监听方法的注解解析器EventListenerMethodProcessor: org.springframework.context.event.internalEventListenerProcessor
	 */
	if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
	}

	/**
	 * 注册事件监听器工厂: org.springframework.context.event.internalEventListenerFactory
	 */
	if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
	}
	return beanDefs;
}

unwrapDefaultListableBeanFactory

        在这个方法中的DefaultListableBeanFactory就是最前面讲的AnnotationConfigApplicationContext进入this()方法的时候,会先进其父类获取DefaultListableBeanFactory对象。

@Nullable
private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {
	// 判断这个配置类是DefaultListableBeanFactory的子类还是GenericApplicationContext的子类
	// 如果是DefaultListableBeanFactory则返回其本身 如果是GenericApplicationContext的子类则返回DefaultListableBeanFactory
	if (registry instanceof DefaultListableBeanFactory) {
		return (DefaultListableBeanFactory) registry;
	} else if (registry instanceof GenericApplicationContext) {
		return ((GenericApplicationContext) registry).getDefaultListableBeanFactory();
	} else {
		return null;
	}
}

        Ok,看到这里,应该重新梳理以下关于AnnotationConfigApplication读取器这个对象中的AnnotationBeanDefinitionReader主要就是对Bean的描述(BeanDefinition)、获取当前的执行环境以及注册各种处理器。

ClassPathBeanDefinitionScanner

        以下就是在这个类中的重载有参构造中传递的顺序。主要是看最后一个有参构造函数

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
	this(registry, true);
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
    this(registry, useDefaultFilters, getOrCreateEnvironment(registry)); // 第三个参数在上面有笔记
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment) {
    this(registry, useDefaultFilters, environment,
         (registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment, @Nullable ResourceLoader resourceLoader) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;// BeanDefinitionRegistry
    if (useDefaultFilters) registerDefaultFilters(); // 从前面传来的是true 所以会进入注册过滤器方法 下面就是方法
    setEnvironment(environment); // 设置环境
    setResourceLoader(resourceLoader); // 设置资源加载器(由前判断传来的BeanDefinitionRegistry)
}

        由于在这些有参构造中传递的第二个参数为true,即useDefaultFilters为true,所以就会进入到registerDefaultFilters()方法,从英文的理解可以猜测这个方法是注册默认的过滤器。此方法内就是寻找注解的类型,找到了就添加进includeFilters链表中,但这里我更在意的是TypeFilter类型。

public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {

	private final List<TypeFilter> includeFilters = new LinkedList<>();

    protected void registerDefaultFilters() {
        // 放置了@Component注解
		this.includeFilters.add(new AnnotationTypeFilter(Component.class));
        // 获取 ClassPathScanningCandidateComponentProvider 的类加载器
		ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
		try {
			// 扫描被 @ManagedBean 注解的类
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
			logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
		} catch (ClassNotFoundException ex) {
			// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
		}
		try {
			// 扫描被 @Named 注解的类
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
			logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
		} catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}
}

        进入了源码发现它是个接口,被函数式接口注解@FunctionalInterface所注解。此内部有个match()方法。

@FunctionalInterface
public interface TypeFilter {

	/**
	 * 确定此筛选器是否与给定元数据所描述的类匹配。
	 * @param metadataReader 目标类的元数据读取器
	 * @param metadataReaderFactory 取元数据读取器的工厂
	 * 对于其他类(如超类和接口)
	 * @return 此筛选器是否匹配
	 * @throws IOException in case of I/O failure when reading metadata
	 */
	boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
			throws IOException;

}

        Ok,以上就是关于ClassPathBeanDefinitionScanner扫描器对象的源码分析,总结以下就是设置环境与资源加载器,并且最主要的是获取被@Component注解的类。

        上面就是对于this()中的源码,一个读取器AnnotatedBeanDefinitionReader与一个扫描器ClassPathBeanDefinitionScanner的源码解读。如果有问题可以在评论区相互探讨。笔者还是个正在成长的小白。

register(componentClasses)

        这些方法还是一样在AnnotatedBeanDefinitionReader对象中,可以看英文意思:registerBean()与doRegisterBean(),可以看出来就是注册Bean对象的方法。可以看到就是将进来的配置类包装成BeanDefinition,再将BeanDefinition包装成BeanDefinitionHolder,再将BeanName与BeanDefinition以键值对的形式放入Map中,此Map为beanDefinitionMap

public void register(Class<?>... componentClasses) {
    Assert.notEmpty(componentClasses, "At least one component class must be specified");
    this.reader.register(componentClasses);
}
public void register(Class<?>... componentClasses) {
    for (Class<?> componentClass : componentClasses) {
        registerBean(componentClass);
    }
}
public void registerBean(Class<?> beanClass) {
    doRegisterBean(beanClass, null, null, null, null);
}
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {
    // 将传入的配置类包装成BeanDefinition
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    //...中间部分省略
    // 在此方法的内部扫描此配置类是否有@Lazy、@Primary、@DependsOn、@Role、@Description这五个注解
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    //...中间部分省略
    // BeanDefinition -> BeanDefinitionHolder 将BeanDefinition包装成BeanDefinitionHolder
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    // 注册BeanDefinitionHolder的BeanDefinition到Map<String, BeanDefinition> beanDefinition
    // 其中Map中的String其实就是BeanName
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

BeanDefinitionReaderUtils.registerBeanDefinition

        下面第一个registerBeanDefinition()方法的第一个代码块是在BeanDefinitionReaderUtils类中的,主要是做的任务就是提取出beanName然后再执行另一个registerBeanDefinition()方法,而这个方法是在DefaultListableBeanFactory中,我放到下面的第二个代码块中。

public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {
    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();
    // 注册BeanDefinitionHolder的BeanDefinition到Map<String, BeanDefinition> beanDefinition
    // 其中String其实就是BeanName
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    // Register aliases for bean name, if any.
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

DefaultListableBeanFactory.registerBeanDefinition

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");

    if (existingDefinition != null) {
        //...省略
    } else {
        if (hasBeanCreationStarted()) {
            //...省略
        } else {
            // Still in startup registration phase
            // 注册BeanDefinitionHolder的BeanDefinition到Map<String, BeanDefinition> beanDefinition
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            removeManualSingletonName(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }
}

        Ok,以上就是register()方法的源码解读了,我认为在这里面主要是将配置类包装成BeanDefinition再包装成BeanDefinitionHolder,然后再将BeanDefinitionHolder中的BeanDefinition放入beanDefinitionMap中。其中key是beanName,就是配置类的类名,value就是Bean的描述。

        第三个refresh()方法我放到下一个博文中再详细说明。这篇已经1.5w字了,有点多。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值