前面講了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