Spring源码学习-IOC(注解扫描方式注册BeanDefinition)

前面讲了Spring IOC 的基本概念和xml配置方式怎么解析为BeanDefinition。感兴趣的可以去了解下 juejin.im/post/5cea6c…

1.基本用法

在一般情况下我们都会在spring配置文件中加入这么一段配置开启自动扫描。

	<context:component-scan base-package="com.study.mike.spring.service">
		<context:exclude-filter type="annotation" expression=""/>
		<context:include-filter type="annotation" expression=""/>
	</context:component-scan> 
复制代码

也可以用Java代码的形式开启自动扫描,第一种方式需要一个配置类并切加上@Configuration、@ComponentScan 这两个注解,第二种方式直接是你要扫描的包路径。两种方式注册BeanDefinition的时机有一点区别,但最终都是通过调用ClassPathBeanDefinitionScanner的doScan()方法扫描注册bean定义的。

@Configuration
@ComponentScan(basePackages="",includeFilters = { @Filter(type = FilterType.CUSTOM, classes = MyTypeFilter.class) })
public class ApplicationTest {
	public static void main(String[] args) {
		// 注解的方式1 
		ApplicationContext context1 = new AnnotationConfigApplicationContext(ApplicationTest.class);
		// 注解的方式2 
		ApplicationContext context2 = new AnnotationConfigApplicationContext("com.study.spring");
		CombatService cs2 = context2.getBean(CombatService.class);
		cs2.combating();
	}
    
}
复制代码

2.源码分析

1.初始化的时候都会调用默认无参构造器初始化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner,初始化 AnnotatedBeanDefinitionReader的时候会注册一些BeanFactoryPostProcessor(该接口的实现能够对BeanFactory再一次处理)类 型的BeanDefinition,这些Bean是spring能够通过注解加载bean的关键。下面是根据调用链画的流程图

最关键的代码在AnnotationConfigUtils中

/**
 * Register all relevant annotation post processors in the given registry.
 * @param registry the registry to operate on
 * @param source the configuration source element (already extracted)
 * that this registration was triggered from. May be {@code null}.
 * @return a Set of BeanDefinitionHolders, containing all bean definitions
 * that have actually been registered by this call
 */
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
		BeanDefinitionRegistry registry, @Nullable Object source) {

	DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
	if (beanFactory != null) {
		if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
			beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
		}
		if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
			beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
		}
	}

	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
    //注册一些BeanFactoryPostProcessor类型的bean
	if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
	//前面说的两种方式的注册BeanDefinition时机的区别就在这,java类当配置类的方式通过该实例最终调用doscan()方法
	//进行注册(该实例的的调用时机在后面章节分析)。
		RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {//@Autowire注解 处理器
		RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
	if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {//JSR-250 注解支持
		RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
	if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {//JPA注解支持
		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));
	}
            //事件监听
	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));
	}

	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;
}
复制代码

2.不管传入的参数是java配置类还是包路径,最终都会调用ClassPathBeanDefinitionScanner的doscan方法,下面看一代码

spring中通过ASM字节码操作库来读取类信息和注解信息,这里最关键的类是MetadataReader的实现类SimpleMetadataReader, 所有的操作都在这个类中处理。下面是调用关系

扫描方式注册Beandefinition的整个过程大致就是这样,如果对其中某一部分感兴趣的可以自己去调试一下,跟一下源码。

猜你喜欢

转载自blog.csdn.net/weixin_34206899/article/details/91375625