目录
一、@Import 注解分析
二、@ImportResource注解分析
三、@bean注解收集分析
spring 源码ConfigurationClassParser类解析收集 Import、ImportResource 、bean等相关注解继续分享,承接上篇文章:
一、@Import 注解分析
此注解非常重要,涉及的功能点也比较多,重要的四点如下:
@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, CollectionimportCandidates, 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()};
}
@Override
public Class extends Group> getImportGroup() {
return DeferredImportSelectorGroupDemo.class;
}
private static class DeferredImportSelectorGroupDemo implements Group {
List 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 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;
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 方法,进入反射生成对象
staticT 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 IterablegetImports() { 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 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, Predicatefilter) 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, Predicatefilter) 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, Predicatefilter) 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注解分析
源码入口
//处理@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注解收集分析
源码入口
//处理@Bean注解,重点 // Process individual @Bean methods //收集有@bean 注解的方法 SetbeanMethods = 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 SetretrieveBeanMethodMetadata(SourceClass sourceClass) { AnnotationMetadata original = sourceClass.getMetadata(); Set 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 asmMethods = asm.getAnnotatedMethods(Bean.class.getName()); if (asmMethods.size() >= beanMethods.size()) { Set 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 对象里,下游业务会详细解析!
到此、六种注解分享完毕,大家一定多多测试,深入理解,定会早日掌握!



