前面讲了Spring IOC 的基本概念和xml配置方式怎么解析为BeanDefinition。感兴趣的能够去了解下 juejin.im/post/5cea6c…java
在通常状况下咱们都会在spring配置文件中加入这么一段配置开启自动扫描。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定义的。express
@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();
}
}
复制代码
1.初始化的时候都会调用默认无参构造器初始化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner,初始化 AnnotatedBeanDefinitionReader的时候会注册一些BeanFactoryPostProcessor(该接口的实现可以对BeanFactory再一次处理)类 型的BeanDefinition,这些Bean是spring可以经过注解加载bean的关键。下面是根据调用链画的流程图bash
最关键的代码在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方法,下面看一代码post
spring中经过ASM字节码操做库来读取类信息和注解信息,这里最关键的类是MetadataReader的实现类SimpleMetadataReader, 全部的操做都在这个类中处理。下面是调用关系ui
扫描方式注册Beandefinition的整个过程大体就是这样,若是对其中某一部分感兴趣的能够本身去调试一下,跟一下源码。this