首先我们编写一个用例,展示下aop的效果;这里我们使用配置类的方式处理;
添加一个配置类AppConfig
这里的重点是添加@EnableAspectJAutoProxy注解,这是开启aop代理;然后编写增强类;
这个类需要添加@Aspect(说明其是增强类)@Component交由spring管理;通过 @Pointcut(“execution(* com.jy.demo.service.UserService.*(…))”)可以看出我们需要增强的是UserService类的方法;
启动demo我们只关注UserService *** 作的方法
通过运行结果我们可以看出在目标方法的前后都做了增强 *** 作,和我们预期的结果是一样的;
那么这样一个过程是怎么实现的呢?我们一步一步来探究一下;
既然@EnableAspectJAutoProxy是开启aop的注解,那么我们就从这个注解开始,进入注解可以看到这个注解引用了@Import(AspectJAutoProxyRegistrar.class),而这个是一个注册器,该类实现了ImportBeanDefinitionRegistrar接口。在类中只有一个方法,主要作用是向容器中注入一个beanName=“org.springframework.aop.config.internalAutoProxyCreator” class=“AnnotationAwareAspectJAutoProxyCreator.class”
进入方法后先调用方法1然后调用重载方法2,最后调用registerOrEscalateApcAsRequired(Class> cls, BeanDefinitionRegistry registry, @Nullable Object source)完成BeanDefinition的注入。
到此注解上的这个注册器类的作用也就完了,但是又有一个问题就是,这个类是什么时候调用的呢?
要搞清这个问题需要先确认AspectJAutoProxyRegistrar是什么时候被spring纳入容器的?带着这些问题,我们进入下一步的研究。
我们知道AspectJAutoProxyRegistrar是通过@Import注解加入spring的,也就是说我们找到spring处理@Import注解的地方就可以找到该类是什么时候加入spring的了。
通过另一篇@Configuration注解解析,我们知道@Import注解是在ConfigurationClassPostProcessor类中处理的,我们就来一探究竟吧。
在调用该类ConfigurationClassPostProcessor中的方法时会先执行postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry),如上图继续调用parser.parse(candidates);然后找到下图标注的方法。
经过重重调用,我们会来到processConfigurationClass(ConfigurationClass configClass, Predicate filter)方法,再往下走来到sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
这里就是处理@Import注解的地方了,会将对应类封装成ConfigurationClass。
到这一步的时候@Import注解的类还没有加入beanDefinitionMap中,还需要上图方法的处理。
进入方法,一路向下我们找到最后一行代码
这里的key就是AspectJAutoProxyRegistrar,那么这里就和我们前面说的联系上了,调用registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)方法完成AnnotationAwareAspectJAutoProxyCreator注入容器。
到此完成了注解类的处理,那么和aop有什么关系呢?这个时候我们就要想想springaop在整个spring周期的哪一步执行了?根据spring的设计原则aop是在bean初始化后才执行的。那么就需要BeanPostProcessor接口的实现了
通过类图我们可以到AnnotationAwareAspectJAutoProxyCreator是间接实现了BeanPostProcessor接口,这样一来又建立起联系了,我们就继续bean的生命周期。
finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)这个是完成对象实例化–>属性填充–>初始化的方法。在这些 *** 作之前会有一个调用后置处理器的过程
进入方法后经过判断会调用applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
再次进入会有一个循环,其中就有我们之前提到的代理构建器,这就是使用的地方。但是在调用postProcessBeforeInstantiation方法时是使用的它的父类的,因为它自己没有实现该方法。
而在postProcessBeforeInstantiation方法中,会先对其增强器做处理
最终这个方法会将所有的增强器放在集合中。到此我们完成了增强器的处理。
最后就剩代理类的创建了,但是我们不要忘了,代理类不是无萍之根,总得有目标对象吧。所以以本例来说,创建UserService的代理类之前,还得先创建目标类就是UserService本身。所以在UserService初始化后的后置处理器中,我们可以去看看是怎么实现aop的。
在这个方法中将完成对象的实例化、属性填充、初始化,当然也包括我们找的aop代理。我们就直接来到aop部分吧。通过前面的介绍我们都知道了,aop是在初始化后的后置处理器完成的,那么我们看看其代码
整个方法可以简单的理解为,先将目标对象赋值给一个临时变量,然后调用方法创建aop代理,如果返回不为空则进行替换,反之返回原来的目标对象。
我们看到调用的依然是AnnotationAwareAspectJAutoProxyCreator父类的方法。
在此会调用wrapIfNecessary(Object bean, String beanName, Object cacheKey)方法。
会先匹配出所有增强方法,然后按顺序进入方法,最终我们会到创建AopProxy的方法,在这个方法中,我们就可以很清晰的看到该使用Cglib代理还是JDK动态代理。
至此我们的代理对象创建就完成了。
以上就是aop的创建过程!!!
希望大家一起努力一起进步!!!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)