在Spring中可以通过实现接口ImportBeanDefinitionRegistrar向Spring容器中注册自己的Bean
第一步
自定义ImportBean类,并实现ImportBeanDefinitionRegistrar接口
public interface ImportBeanDefinitionRegistrar {
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {}
}
//实现类---这个是Spring-AOP事务的核心入口
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
//实现接口方法(由于接口有默认实现)这里算重写吧
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
加上一个自定义的ImportBean(自己写的一个示例)
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
System.out.println("===========MyImportBeanDefinitionRegistrar.registerBeanDefinitions");
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
beanDefinition.setBeanClass(ImportImportBeanDefinitionRegistrar.class);
//beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(cla);
registry.registerBeanDefinition(ImportImportBeanDefinitionRegistrar.class.getName(), beanDefinition);
}
}
第二步
如何使用?
需要在启动类或者配置类中导入自定义的ImportBean
//告诉spring这个是一个配置类
@Configuration
@Import({MyImportBeanDefinitionRegistrar.class})
@EnableAspectJAutoProxy
public class MainConfig2 {
}
第一个分析
(1)通过@Import注解导入自定义的ImportBean
这样在Spring启动的时候,会加载配置类及上面的相关注解
(2)@EnableAspectJAutoProxy 这个是要开启AOP的配置
注解内部实现
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)//这里也实现了@Import来导入AspectJAutoProxyRegistrar
public @interface EnableAspectJAutoProxy {
}
在看AspectJAutoProxyRegistrar代码,他肯定实现了接口ImportBeanDefinitionRegistrar
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
...
}
由此总结
事务、IOC等都是通过这种方式将Bean定义注册到BeanFactory中
第三步
知其然,必要知其所以然!为什么通过实现ImportBeanDefinitionRegistrar接口,然后在启动类加入@Import导入后,就可以实现呢?Spring的执行流程是什么呢?
这个先要通过DEBUG来分析!
查看调用链路
执行分析(代码方法级别)
执行流程
(1)传入配置类,创建IOC容器
AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
(2)注册配置类
register(componentClasses);
(3)刷新Spring容器
refresh();
(1)invokeBeanFactoryPostProcessors(beanFactory)
调用beanFactory的后处理器,这些后处理器是在bean定义中向容器注册的,用户自定义的Spring的各种内置处理,都是在这个地方进行初始化的。比如:自定义ResourceEditorRegistrar;
对priorityOrderedPostProcessors,orderedPostProcessors,BeanDefinitionRegistryPostProcessor进行注册,然后,在按顺序实例化,提前实例化这些接口下的bean。
(1)PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
//在spring容器中查找BeanDefinitionRegistryPostProcessor.class类型的bean,然后通过OrderComparator进行排序
(1)invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)
//currentRegistryProcessors:list里面有ConfigurationClassPostProcessor的实例
//org.springframework.context.annotation.ConfigurationClassPostProcessor注册到beanDefinition中【@Configuration】注解实现
//这里可以理解registry=beanFactory 实现了接口BeanDefinitionRegistry
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(registry)调用
(1)processConfigBeanDefinitions(registry)---ConfigurationClassPostProcessor的方法
(1)ConfigurationClassParser.parse(candidates)BeanDefinitionHolder持有beanDefinition
AnnotatedBeanDefinition.parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName())
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
--processConfigurationClass
--doProcessConfigurationClass(configClass, sourceClass, filter)【关键方法】处理@Configuration配置类上面的标签信息
(1)processImports(configClass, sourceClass, getImports(sourceClass), filter, true)
//这里我们分析的是@Import,所以只关心@Import即可
(1)ImportBeanDefinitionRegistrar registrar =
//通过ParserStrategy工具类,处理ImportBeanDefinitionRegistrar类型
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry)
//importCandidates是一个集合,里面装的是@Import注解里面导入的.class(例如:@Import({Dog.class,MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}))
//importCandidates=[Dog.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class]
//@Import里面会处理三种类型的注解
//(1)ImportSelector(2)ImportBeanDefinitionRegistrar 【这个是我们本次分析需要的】 (3)普通的.class
(1)org.springframework.context.annotation.ParserStrategyUtils.instantiateClass
(1)createInstance(clazz, environment, resourceLoader, registry, classLoader)
//这里就是对MyImportBeanDefinitionRegistrar进行实例化;new MyImportBeanDefinitionRegistrar()
//使用BeanUtils.instantiateClass(clazz)
//执行完毕后,拿到ImportBeanDefinitionRegistrar的实例,然后放到ConfigurationClass的importBeanDefinitionRegistrars属性中,相当于给某个属性赋值
(2)this.reader.loadBeanDefinitions(configClasses) reader:ConfigurationClassBeanDefinitionReader
//将Configuration加载到BeanDefinition
(1)org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions
(1)loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()) 从ConfigurationClass的importBeanDefinitionRegistrars属性中拿到beanDefinition注册信息,加载beanDefinition
(1)ImportBeanDefinitionRegistrar.registerBeanDefinitions
//方法里面有基于configClass.getImportBeanDefinitionRegistrars()的循环Map<ImportBeanDefinitionRegistrar, AnnotationMetadata>类型
//org.springframework.context.annotation.ImportBeanDefinitionRegistrar.registerBeanDefinitions
(1)由于importBeanDefinitionRegistrars里面包含包含MyImportBeanDefinitionRegistrar所以最终的registerBeanDefinitions就是
//MyImportBeanDefinitionRegistrar的registerBeanDefinitions方法,registerBeanDefinitions参数
//AnnotationMetadata ConfigurationClass的metadata属性,配置类的注解信息,BeanDefinitionRegistry registry bean定义注册器(org.springframework.beans.factory.support.DefaultListableBeanFactory实例)
//其实就是beanFactory
图文模式
总结
- 读取@Configuration注解,并加载形成ConfigurationClass对象
- 然后通过对ConfigurationClass里面的importBeanDefinitionRegistrars,导入的@Import注解进行解析实例化和加载
- 在通过判断其类型是ImportBeanDefinitionRegistrar,调用其方法registerBeanDefinitions,从而实现了对自定义(MyImportBeanDefinitionRegistrar方法registerBeanDefinitions的调用)【这里只要是ImportBeanDefinitionRegistrar类型的实例都可以被调用】
- 到时候分析AOP之事务的时候,思路跟这个一模一样。后记!!!AOP之事务@EnableAspectJAutoProxy