目录
spring 源码ConfigurationClassParser类解析收集 Import、ImportResource 、bean等相关注解继续分享,承接上篇文章:
此注解非常重要,涉及的功能点也比较多,重要的四点如下:
@Import的作用是创建Spring bean,具体有四种用法
1) 导入普通类,即将普通类变为bean
2) 导入@Configuration,即将该注解生效,具体来说就是:将其注解的类成为bean,该类中的@Bean注解的方法也变为bean。注:在应用启动类上使用@ComponentScan也能让@Configuration生效
3) 导入ImportSelector的实现类。ImportSelector接口中定义了方法selectImports,它返回字符串数组,里面是类的全路径。使用@Import导入ImportSelector的实现类,就是将selectImports方法返回的类注册为bean
4)导入ImportBeanDefinitionRegistrar的实现类。ImportBeanDefinitionRegistrar接口中定义了方法registerBeanDefinitions,它的功能就是通过BeanDefinitionRegistry实例注册bean。
这四点功能下面会通过源码结合业务代码详细验证,源码入口如下:
- //处理@Import注解 getImports(sourceClass) 获取类上面的@Import注解并封装成SourceClass
- // Process any @Import annotations
- processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
点击进入
- private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
- Collection
importCandidates, Predicate exclusionFilter, - boolean checkForCircularImports) {
-
- //如果没有@Import注解直接返回,不处理
- if (importCandidates.isEmpty()) {
- return;
- }
-
- if (checkForCircularImports && isChainedImportOnStack(configClass)) {
- this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
- }
- else {
- this.importStack.push(configClass);
- try {
- //循环类上面的每一个@Import
- for (SourceClass candidate : importCandidates) {
- //如果Import进来的是一个ImportSelector类型
- if (candidate.isAssignable(ImportSelector.class)) {
- // Candidate class is an ImportSelector -> delegate to it to determine imports
- Class> candidateClass = candidate.loadClass();
- //反射实例化
- ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
- this.environment, this.resourceLoader, this.registry);
- Predicate
selectorFilter = selector.getExclusionFilter(); - if (selectorFilter != null) {
- exclusionFilter = exclusionFilter.or(selectorFilter);
- }
- //如果是一个DeferredImportSelector类型
- if (selector instanceof DeferredImportSelector) {
- //比较复杂,springboot中自动配置用到了
- this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
- }
- else {
- //在这里调用selectImports方法,返回所有的需要import到spring容器的beanName,这里直接调用了。
- String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
- Collection
importSourceClasses = asSourceClasses(importClassNames, exclusionFilter); - //递归处理,有可能import进来的类又有@Import注解
- processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
- }
- }
- //如果Import进来的是一个ImportBeanDefinitionRegistrar类型,而此接口的实现类此代码块没有调用,而是在对象实例化完成之后才调用,这就是和上面接口的差异
- else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
- // Candidate class is an ImportBeanDefinitionRegistrar ->
- // delegate to it to register additional bean definitions
- Class> candidateClass = candidate.loadClass();
- //反射实例化
- ImportBeanDefinitionRegistrar registrar =
- ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
- this.environment, this.resourceLoader, this.registry);
- //加入到importBeanDefinitionRegistrars容器中,这里还没有调用registerBeanDefinitions
- configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
- }
- else {
- // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
- // process it as an @Configuration class
- this.importStack.registerImport(
- currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
- //如果都不是,则走这里
- processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
- }
- }
- }
- catch (BeanDefinitionStoreException ex) {
- throw ex;
- }
- catch (Throwable ex) {
- throw new BeanDefinitionStoreException(
- "Failed to process import candidates for configuration class [" +
- configClass.getMetadata().getClassName() + "]", ex);
- }
- finally {
- this.importStack.pop();
- }
- }
- }
测试数据
进入

1、测试的伪代码如下
-
-
- import com.enjoy.jack.aware.AwareBean;
- import org.springframework.context.annotation.Import;
- import org.springframework.stereotype.Component;
-
-
- @Component
- //Import虽然是实例化一个类,Import进来的类可以实现一些接口
- @Import({DeferredImportSelectorDemo.class,LisonSelectImport.class,JamesImportBeanDefinitionRegistrar.class, AwareBean.class})
- public class ImportBean {
- //省略......
- }
DeferredImportSelectorDemo 类
- import org.springframework.context.annotation.DeferredImportSelector;
- import org.springframework.core.type.AnnotationMetadata;
-
- import java.util.ArrayList;
- import java.util.List;
-
-
- public class DeferredImportSelectorDemo implements DeferredImportSelector {
-
- //这个接口是下面的 String[] strings = selector.selectImports(metadata); 来调用
- //即如果没有下面的调用,源码是不会调用这里的,因为你实现的是 DeferredImportSelector 接口
- @Override
- public String[] selectImports(AnnotationMetadata importingClassMetadata) {
- System.out.println("=====DeferredImportSelectorDemo.selectImports");
- // return new String[]{SelectImportBean.class.getName()};
- return new String[]{SelectImportBean.class.getName()};
- }
-
- /**
- * 要返回一个实现了Group接口的类,这个内部类没有的话,下面几个接口是不会调用的
- 可以结合源码测试一下
- */
- @Override
- public Class extends Group> getImportGroup() {
- return DeferredImportSelectorGroupDemo.class;
- }
-
- private static class DeferredImportSelectorGroupDemo implements Group {
-
- List<Entry> list = new ArrayList<>();
- /**
- 收集需要实例化的类
- */
- @Override
- public void process(AnnotationMetadata metadata, DeferredImportSelector selector) {
- System.out.println("=====DeferredImportSelectorGroupDemo.process");
- String[] strings = selector.selectImports(metadata);
- for (String string : strings) {
- list.add(new Entry(metadata,string));
- }
- }
-
- @Override
- public Iterable<Entry> selectImports() {
- System.out.println("=====DeferredImportSelectorGroupDemo.selectImports");
- return list;
- }
- }
- }
继续继承
public interface DeferredImportSelector extends ImportSelector {
LisonSelectImport 类
- import com.enjoy.jack.bean.Nandao;
- import org.springframework.context.annotation.ImportSelector;
- import org.springframework.core.type.AnnotationMetadata;
-
- /**
- * @Author Nandao
- * LisonSelectImport 此类不会被实例化到spring容器中;如果不实现ImportSelector接口,会实例化到容器中
- */
- public class LisonSelectImport implements ImportSelector {
- @Override
- public String[] selectImports(AnnotationMetadata importingClassMetadata) {
- // MergedAnnotations annotations = importingClassMetadata.getAnnotations();
- // MergedAnnotation
eas = annotations.get(EnableAspectJAutoProxy.class); -
- // Object proxyTargetClass = eas.getValue("proxyTargetClass").get();
- //类的完整限定名,
- System.out.println("nandao is OK");
- return new String[]{Nandao.class.getName()};
- }
- }
比如测试:
- @Test
- public void test4() {
- AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanBean.class);
- LisonSelectImport bean = applicationContext.getBean(LisonSelectImport.class);
- System.out.println(bean);
- }
测试结果

JamesImportBeanDefinitionRegistrar 类
- import com.enjoy.jack.bean.BeanDefinitionBean;
- import org.springframework.beans.MutablePropertyValues;
- import org.springframework.beans.factory.support.BeanDefinitionRegistry;
- import org.springframework.beans.factory.support.GenericBeanDefinition;
- import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
- import org.springframework.core.type.AnnotationMetadata;
-
-
- public class JamesImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
- @Override
- public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
- //自己创建beanDefinition对象,然后注册到BeanDefinitionRegistry中
- GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
- genericBeanDefinition.setBeanClass(BeanDefinitionBean.class);
- MutablePropertyValues propertyValues = genericBeanDefinition.getPropertyValues();
- propertyValues.add("name","Jack");
- registry.registerBeanDefinition("beanDefinitionBean",genericBeanDefinition);
- }
- }
AwareBean 类
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.BeanFactory;
- import org.springframework.beans.factory.BeanFactoryAware;
- import org.springframework.beans.factory.BeanNameAware;
- import org.springframework.beans.factory.InitializingBean;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.ApplicationContextAware;
- import org.springframework.context.EnvironmentAware;
- import org.springframework.context.annotation.ImportAware;
- import org.springframework.core.annotation.MergedAnnotations;
- import org.springframework.core.env.Environment;
- import org.springframework.core.type.AnnotationMetadata;
-
-
- public class AwareBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, EnvironmentAware, ImportAware, InitializingBean {
- @Override
- public void setBeanName(String name) {
- System.out.println(name);
- }
-
- @Override
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- System.out.println(beanFactory);
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- System.out.println(applicationContext);
- }
-
- @Override
- public void setEnvironment(Environment environment) {
- System.out.println(environment);
- }
-
- @Override
- public void setImportMetadata(AnnotationMetadata importMetadata) {
- //这个方法就是要拿到注解的值
- MergedAnnotations annotations = importMetadata.getAnnotations();
- }
-
- @Override
- public void afterPropertiesSet() throws Exception {
- System.out.println("========afterPropertiesSet");
- }
- }
2、源码开始遍历

点击 ParserStrategyUtils.instantiateClass 方法,进入反射生成对象
- static
T instantiateClass(Class> clazz, Class assignableTo, Environment environment, - ResourceLoader resourceLoader, BeanDefinitionRegistry registry) {
-
- Assert.notNull(clazz, "Class must not be null");
- Assert.isAssignable(assignableTo, clazz);
- if (clazz.isInterface()) {
- throw new BeanInstantiationException(clazz, "Specified class is an interface");
- }
- ClassLoader classLoader = (registry instanceof ConfigurableBeanFactory ?
- ((ConfigurableBeanFactory) registry).getBeanClassLoader() : resourceLoader.getClassLoader());
- T instance = (T) createInstance(clazz, environment, resourceLoader, registry, classLoader);
- ParserStrategyUtils.invokeAwareMethods(instance, environment, resourceLoader, registry, classLoader);
- return instance;
- }
返回后生成一个空对象
进入这里 this.deferredImportSelectorHandler.handle(),点击进入
- public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
- DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
- if (this.deferredImportSelectors == null) {
- //创建DeferredImportSelectorGroup接口的处理类
- DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
- handler.register(holder);//点击进入
- handler.processGroupImports();//点击进入
- }
- else {
- this.deferredImportSelectors.add(holder);
- }
- }
3、点击 handler.register(holder);来到
- public void register(DeferredImportSelectorHolder deferredImport) {
- //调用getImportGroup方法,返回实现了Group接口的类
- Class extends Group> group = deferredImport.getImportSelector().getImportGroup();
- //建立实现了Group接口类和DeferredImportSelectorGrouping的映射关系
- DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
- (group != null ? group : deferredImport),
- key -> new DeferredImportSelectorGrouping(createGroup(group)));
- grouping.add(deferredImport);
- this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
- deferredImport.getConfigurationClass());
- }
点击deferredImport.getImportSelector().getImportGroup();进入业务方法

点击 handler.processGroupImports();
- public void processGroupImports() {
- for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
- Predicate
exclusionFilter = grouping.getCandidateFilter(); - //这里调用了 group.selectImports()
- grouping.getImports().forEach(entry -> {
- ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
- try {
- //又递归处理每一个返回的Entry
- processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
- Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
- exclusionFilter, false);
- }
- catch (BeanDefinitionStoreException ex) {
- throw ex;
- }
- catch (Throwable ex) {
- throw new BeanDefinitionStoreException(
- "Failed to process import candidates for configuration class [" +
- configurationClass.getMetadata().getClassName() + "]", ex);
- }
- });
- }
- }
点击grouping.getImports()
- public Iterable
getImports() { - for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
- //进入业务方法
- this.group.process(deferredImport.getConfigurationClass().getMetadata(),
- deferredImport.getImportSelector());
- }
- //在这里调用了实现了Group接口的selectImports方法,进入业务方法
- return this.group.selectImports();
- }
点击this.group.process方法

点击this.group.selectImports() 进入业务方法

如果不是第一次就会放入
this.deferredImportSelectors.add(holder);
下游业务会执行

点击进入
- public void process() {
- List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
- this.deferredImportSelectors = null;
- try {
- if (deferredImports != null) {
- DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
- deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
- deferredImports.forEach(handler::register);
- handler.processGroupImports();//此处执行
- }
- }
- finally {
- this.deferredImportSelectors = new ArrayList<>();
- }
- }
4、遍历到第二个对象

往下走到这里进入业务方法 selectImports

业务方法

5、 第三次遍历

、
6、第四次遍历

点击 processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
- protected void processConfigurationClass(ConfigurationClass configClass, Predicate
filter) throws IOException { - //对@Condition注解的支持,过滤掉不需要实例化的类
- if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
- return;
- }
-
- ConfigurationClass existingClass = this.configurationClasses.get(configClass);
- if (existingClass != null) {
- if (configClass.isImported()) {
- if (existingClass.isImported()) {
- existingClass.mergeImportedBy(configClass);
- }
- // Otherwise ignore new imported config class; existing non-imported class overrides it.
- return;
- }
- else {
- // Explicit bean definition found, probably replacing an import.
- // Let's remove the old one and go with the new one.
- this.configurationClasses.remove(configClass);
- this.knownSuperclasses.values().removeIf(configClass::equals);
- }
- }
-
- //这个对象理解为跟类或者接口对应,然后把metadata对象包装进去了
- // Recursively process the configuration class and its superclass hierarchy.
- SourceClass sourceClass = asSourceClass(configClass, filter);
- do {
- //核心代码,认真读
- sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
- }
- while (sourceClass != null);
-
- this.configurationClasses.put(configClass, configClass);
- }
点击asSourceClass(configClass, filter);
- private SourceClass asSourceClass(ConfigurationClass configurationClass, Predicate
filter) throws IOException { - AnnotationMetadata metadata = configurationClass.getMetadata();
- if (metadata instanceof StandardAnnotationMetadata) {
- return asSourceClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass(), filter);
- }
- return asSourceClass(metadata.getClassName(), filter);
- }
点击 asSourceClass(metadata.getClassName(), filter);
- SourceClass asSourceClass(@Nullable String className, Predicate
filter) throws IOException { - if (className == null || filter.test(className)) {
- return this.objectSourceClass;
- }
- if (className.startsWith("java")) {
- // Never use ASM for core java types
- try {
- return new SourceClass(ClassUtils.forName(className, this.resourceLoader.getClassLoader()));
- }
- catch (ClassNotFoundException ex) {
- throw new NestedIOException("Failed to load class [" + className + "]", ex);
- }
- }
- return new SourceClass(this.metadataReaderFactory.getMetadataReader(className));
- }
返回点击 sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
进入循环递归调用环节
最后收集的对象在这里调用

进入

即里面实现的接口最终都会系统调用。
总之,分析此注解得出结论:
1)声明一个bean
2)导入@Configuration注解的配置类
3)导入ImportSelector的实现类
4)导入ImportBeanDefinitionRegistrar的实现类
即@Import用来导入@Configuration注解的配置类、声明@Bean注解的bean方法、导入ImportSelector的实现类或导入ImportBeanDefinitionRegistrar的实现类。
源码入口
- //处理@ImportResource注解 ,加载xml配置文件
- // Process any @ImportResource annotations
- AnnotationAttributes importResource =
- AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
- if (importResource != null) {
- String[] resources = importResource.getStringArray("locations");
- Class extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
- for (String resource : resources) {
- String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
- //建立xml文件和reader的映射关系
- configClass.addImportedResource(resolvedResource, readerClass);
- }
- }
比如业务场景
- @ImportResource("classpath:spring.xml")
- public class ImportBean {
- //省略......
- }
此处源码仅仅是加载保存,下游业务解析时会用到。
源码入口
- //处理@Bean注解,重点
- // Process individual @Bean methods
- //收集有@bean 注解的方法
- Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
- for (MethodMetadata methodMetadata : beanMethods) {
- //加入到ConfigurationClass中
- configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
- }
-
- //处理接口里面方法有@Bean注解的,逻辑差不多
- // Process default methods on interfaces
- processInterfaces(configClass, sourceClass);
1、点击 retrieveBeanMethodMetadata(sourceClass);方法
- private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
- AnnotationMetadata original = sourceClass.getMetadata();
- Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
- if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
- // Try reading the class file via ASM for deterministic declaration order...
- // Unfortunately, the JVM's standard reflection returns methods in arbitrary
- // order, even between different runs of the same application on the same JVM.
- try {
- AnnotationMetadata asm =
- this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
- Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
- if (asmMethods.size() >= beanMethods.size()) {
- Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
- for (MethodMetadata asmMethod : asmMethods) {
- for (MethodMetadata beanMethod : beanMethods) {
- if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
- selectedMethods.add(beanMethod);
- break;
- }
- }
- }
- if (selectedMethods.size() == beanMethods.size()) {
- // All reflection-detected methods found in ASM method set -> proceed
- beanMethods = selectedMethods;
- }
- }
- }
- catch (IOException ex) {
- logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
- // No worries, let's continue with the reflection metadata we started with...
- }
- }
- return beanMethods;
- }
2、点击 processInterfaces(configClass, sourceClass);
- private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
- for (SourceClass ifc : sourceClass.getInterfaces()) {
- //找方法上有@Bean的注解
- Set
beanMethods = retrieveBeanMethodMetadata(ifc); - for (MethodMetadata methodMetadata : beanMethods) {
- if (!methodMetadata.isAbstract()) {
- // A default method or other concrete method on a Java 8+ interface...
- configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
- }
- }
- processInterfaces(configClass, ifc);//循环递归查询
- }
- }
收集完之后 作为参数封装到 ConfigurationClass 对象里,下游业务会详细解析!
到此、六种注解分享完毕,大家一定多多测试,深入理解,定会早日掌握!