Spring基于注解开发的注解使用之AOP-ImportBeanDefinitionRegistrar接口实现类执行

在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

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值