目录
一、@Import 注解分析
二、@ImportResource注解分析
三、@bean注解收集分析
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 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;
/**
* @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 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 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 retrieveBeanMethodMetadata(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 对象里,下游业务会详细解析!
到此、六种注解分享完毕,大家一定多多测试,深入理解,定会早日掌握!