基于SpringBoot2.3.1进行AOP原理源码阅读
1、AOP是什么
首先应该都知道什么是AOP:
那么我们通常如何使用AOP?
1、我们普通的业务逻辑类
2、切面类,里面创建目标方法,通过自定义表达式去确定我们去监听那些业务逻辑类的普通方法运行,然后加上我们自己的逻辑
3、通知注解,告知我们的目标方法应该在普通方法运行的何时去执行。
通知方法:
前置通知(@Before):logStart:在目标方法运行之前运行
后置通知(@After):logEnd:在目标方法运行结束之后运行(无论方法正常结束还是异常结束)
返回通知(@AfterReturning):logReturn:在目标方法正常返回之后运行
异常通知(@AfterThrowing):logException:在目标方法出现异常以后运行
环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
4、确保我们的业务逻辑类和切面类都放到类spring容器中
5、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】
2、SpringBoot中又是如何开始的?
2、1 有关@EnableAspectJAutoProxy
其实之前使用的有疑问,为什么@EnableAspectJAutoProxy这个注解用不到了,前几天看完SpringBoot自动配置源码,今天一想应该还是与这有关吧,看看代码,提到自动配置,还是到autoconfigure包下
看到里面有一个aop配置类,打开看一下
/** * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration * Auto-configuration} for Spring's AOP support. Equivalent to enabling * {@link EnableAspectJAutoProxy @EnableAspectJAutoProxy} in your configuration. * <p> * The configuration will not be activated if {@literal spring.aop.auto=false}. The * {@literal proxyTargetClass} attribute will be {@literal true}, by default, but can be * overridden by specifying {@literal spring.aop.proxy-target-class=false}. * * @author Dave Syer * @author Josh Long * @since 1.0.0 * @see EnableAspectJAutoProxy */ @Configuration(proxyBeanMethods = false)
//看上面注释可以知道,只有当我们在配置文件中设置spring,aop.auto=false时,这个自动配置类才不会生效 @ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true) public class AopAutoConfiguration { @Configuration(proxyBeanMethods = false)
//只有当我们引入aop组件,也就是包含Advice时,此类才会生效 @ConditionalOnClass(Advice.class) static class AspectJAutoProxyingConfiguration { @Configuration(proxyBeanMethods = false)
//可以看到在这使用了这个注解 @EnableAspectJAutoProxy(proxyTargetClass = false)
//当重写spring.aop.proxy-tartget-class=false时,会使用本地动态代理 @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false) static class JdkDynamicAutoProxyConfiguration { } @Configuration(proxyBeanMethods = false) @EnableAspectJAutoProxy(proxyTargetClass = true)
//默认使用Cglib的动态代理 @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true) static class CglibAutoProxyConfiguration { } } @Configuration(proxyBeanMethods = false) @ConditionalOnMissingClass("org.aspectj.weaver.Advice") @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true) static class ClassProxyingConfiguration { ClassProxyingConfiguration(BeanFactory beanFactory) { if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } } } }
2.2 那么@EnableAspectJAutoProxy又有啥用
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented //里面向spring容器中引入类AspectJAutoProxyRegistrar @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy {
打开AspectJAutoProxyRegistrar,里面只实现了一个方法,重点也就是
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { /** * Register, escalate, and configure the AspectJ auto proxy creator based on the value * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing * {@code @Configuration} class. */ @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //创建了一个AspectJAnnotationAutoProxyCreator的bean定义信息
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); } } } }
看看到底这个定义的BeanDefinition是啥
@Nullable public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary( BeanDefinitionRegistry registry, @Nullable Object source) { //可以看出是注册一个AnnotationAwareAspectJAutoProxyCreator类型的Bean return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); } @Nullable private static BeanDefinition registerOrEscalateApcAsRequired( Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); //查看容器中有没有org.springframework.aop.config.internalAutoProxyCreator这个名字的bean,第一次肯定没有 if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); //创建一个名字叫org.springframework.aop.config.internalAutoProxyCreator的bean定义信息,bean的类型是AnnotationAwareAspectJAutoProxyCreator registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }
那AnnotationAwareAspectJAutoProxyCreator在容器中有啥用?
看一下继承结构
AnnotationAwareAspectJAutoProxyCreator:
AnnotationAwareAspectJAutoProxyCreator
->AspectJAwareAdvisorAutoProxyCreator
->AbstractAdvisorAutoProxyCreator
->AbstractAutoProxyCreator
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
发现最根本上是继承了两个接口,一个是
SmartInstantiationAwareBeanPostProcessor 后置处理器,在bean初始化前后进行工作
BeanFactoryAware 自动装配BeanFactory
2.3 那么AnnotationAwareAspectJAutoProxyCreator是什么时候创建注册到容器中的,打个断点看下方法栈
可以看到是在之前看SpringBoot启动源码的时候refresh刷新容器方法里面的invokeBeanFactoryPostProcessors()方法添加了AnnotationAwareAspectJAutoProxyCreator的Bean定义信息,那什么时候注册的呢?
看下方法栈,是在
refresh的registerBeanPostProcessors(beanFactory)中进行后置处理器bean的创建,那么在doCreateBean中主要干了哪几件事?挑出里面重要的方法
1、创建
类型的bean
// Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance();
2、
给bean的属性赋值,并初始化bean
try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); }
看看初始化bean做了哪些事
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { //处理Aware接口的方法回调,也就是调用setBeanFactory方法把当前所处的BeanFactory放入 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //应用后置处理器的postProcessBeforeInitialization() wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //执行自定义的初始化方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { //执行后置处理器的postProcessAfterInitialization() wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
2.4 应用类的方法是如何被后置处理器处理的?
其实普通bean的对象和后置处理器bean创建前期没有太多区别,可以看下方法栈
创建一个bean无非就是先看有没有创建,缓存里面有没有,那么后置处理器对我们普通对象的操作也就是发生在createBean方法里面
try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } }
通过注释可以看出对每一个bean创建之前返回一个代理的机会,点进去看一下
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }
会看到首先会执行
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
@Nullable protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); if (result != null) { return result; } } } return null; }
判断是不是
InstantiationAwareBeanPostProcessor
类型,也就是我们的AnnotationAwareAspectJAutoProxyCreator,从这可以看出这种后置器并不是在bean初始化前后执行,而是在bean创建之前尝试返回一个bean,
会执行
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
我们直接到
AnnotationAwareAspectJAutoProxyCreator
的这个方法中看看到底做了什么
@Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { //先看所有增强类集合中有没有这个类名 if (this.advisedBeans.containsKey(cacheKey)) { return null; } //判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean,或者是否是切面(@Aspect)是否需要跳过 //1)、获取候选的增强器(切面里面的通知方法)【List<Advisor> candidateAdvisors】 // 每一个封装的通知方法的增强器是 InstantiationModelAwarePointcutAdvisor; // 判断每一个增强器是否是 AspectJPointcutAdvisor 类型的;返回true // 2)、永远返回false if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } // 跳过 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null; }
从上面看出并没有做什么具体操作,那么看看创建对象后做了什么
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean; }
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice.
//得到当前bean的增强器,通过循环判断切入点表达式来找到
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//创建代理对象如果有通知方法
if (specificInterceptors != DO_NOT_PROXY) {
//放到需要增强类集合中 this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建代理对象,默认是cglg,最开始有看过 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
从这应用类的代理对象就创建好并放到集合中了