前面讲了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的整个过程大致就是这样,如果对其中某一部分感兴趣的可以自己去调试一下,跟一下源码。