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; }
從這應用類的代理對象就創建好並放到集合中了