基本概念
AOP 是面向切面|面向方面程式設計的簡稱,Aspect-Oriented Programming。 Aspect 是一種子產品化機制,是用來描述分散在對象,類,函數中的橫切關注點。從關注點分離出橫切關注點是面向切面的程式設計的核心概念。分離關注點使解決特定領域問題的代碼從業務邏輯中獨立出來,業務邏輯的代碼中不在含有針對特定領域問題的代碼調用,業務邏輯和特定領域的問題的關系通過切面來封裝,維護,這樣原本分散在整個程式中的變動就可以很好的管理起來了。
基礎: 待增強對象或者目标對象
切面: 包含對基礎的增強應用
配置: 可以看成一種編織,通過在AOP體系中提供這個配置環境,将基礎和切面結合起來,進而完成切面對目标對象的編織實作
Advice(通知): 定義在連接配接點做什麼,為切面增強提供織入接口。在Spring AOP 中,它主要描述Spring AOP 圍繞方法調用而注入的切面行為。
Pointcut(切點):決定Advice通知應該作用于哪個連接配接點,也就是說通過Pointcut來定義需要增強的方法集合。
Advisor(通知器):完成對目标方法的切面增強設計(advice)和關注點的設計以後,需要一個對象把它們結合起來,完成這個作用的就是Advisor(通知器)。通過Advisor ,可以定義應該使用那個通知并在哪個關注點使用它。
源碼分析
### 啟動過程
在Sprint Boot 啟動類上加入 注解
@EnableAspectJAutoProxy(proxyTargetClass = true)
,注解源碼為:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
該注解使用 @Import 注解引入
AspectJAutoProxyRegistrar
, 跟蹤
AspectJAutoProxyRegistrar
類:
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) {
/*
往容器中注入AnnotationAwareAspectJAutoProxyCreator類,bean名稱為 org.springframework.aop.config.internalAutoProxyCreator
*/
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
/*
讀取主配置類的 EnableAspectJAutoProxy的注解的屬性
*/
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata,
EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
通過源碼發現,
AspectJAutoProxyRegistrar
類 實作了
ImportBeanDefinitionRegistrar
接口,在容器啟動的時候會調用所有實作
ImportBeanDefinitionRegistrar
的 bean 的
registerBeanDefinitions
方法。在方法内部:
1.調用
org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry)
a. 在`registerAspectJAnnotationAutoProxyCreatorIfNecessary` 方法内部:
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);
}
- 最終調用
方法, 參數cls 為org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired
AnnotationAwareAspectJAutoProxyCreator.class
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(
"org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition apcDefinition = registry.getBeanDefinition(
"org.springframework.aop.config.internalAutoProxyCreator");
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(
apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
} else {
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", -2147483648);
beanDefinition.setRole(2);
registry.registerBeanDefinition(
"org.springframework.aop.config.internalAutoProxyCreator",
beanDefinition);
return beanDefinition;
}
}
在方法内部, 首先檢查容器中是否包含名稱為
org.springframework.aop.config.internalAutoProxyCreator
的bean ,容器第一次啟動總不包含該bean,進入else 邏輯,建立一個
AnnotationAwareAspectJAutoProxyCreator.class
的bean定義,并且注冊bean的名稱為
AnnotationAwareAspectJAutoProxyCreator.class
2.調用
org.springframework.context.annotation.AnnotationConfigUtils#attributesFor(org.springframework.core.type.AnnotatedTypeMetadata, java.lang.Class<?>)
該類主要完成 讀取主配置類的
EnableAspectJAutoProxy
的注解的屬性。 主要檢查
proxyTargetClass
和
exposeProxy
屬性的值
AnnotationAwareAspectJAutoProxyCreator
在容器啟動的過程中, AOP 向容器中注入了一個
AnnotationAwareAspectJAutoProxyCreator
的 bean , 我們來分析一下這個bean 。
類的繼承體系 :

通過 類的繼承體系,我們發現
AnnotationAwareAspectJAutoProxyCreator
實作了 BeanFactoryAware ,BeanClassLoaderAware, SmartInstantiationAwareBeanPostProcessor,InstantiationAwareBeanPostProcessor , BeanPostProcessor , BeanClassLoaderAware 等接口 來介入容器啟動過程容Bean的生命周期。
類的接口實作:
在
AnnotationAwareAspectJAutoProxyCreator
的接口實作中:
BeanFactoryAware接口:
定義了setBeanFactory 接口, 在容器啟動的時候調用
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#setBeanFactory
:
@Override
public void setBeanFactory(BeanFactory beanFactory) {
// 設定容器
super.setBeanFactory(beanFactory);
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException(
"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
}
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 建立增強器探索工具
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}
其中initBeanFactory 最終調用
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#initBeanFactory
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 調用父類的initBeanFactory方法
super.initBeanFactory(beanFactory);
if (this.aspectJAdvisorFactory == null) {
// 建立Aspect增強器工廠
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
// 建立一個增強器的建構器
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
InstantiationAwareBeanPostProcessor接口:
我們知道在spring 容器建立任意一個bean的過程中。在
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
的方法中:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// ... 省略代碼
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;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
//... 省略代碼
}
在調用真正建立bean的方法
doCreateBean
之前, 先調用了
resolveBeforeInstantiation
方法。 我們跟蹤
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
方法:
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.
// 當容器中存在InstantiationAwareBeanPostProcessors 時,調用InstantiationAwareBeanPostProcessors 的 postProcessBeforeInstantiation 方法和 postProcessAfterInitialization 方法
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;
}
當容器中存在
InstantiationAwareBeanPostProcessors
的bean時
1.先調用
applyBeanPostProcessorsBeforeInstantiation
方法,
2.然後在調用
applyBeanPostProcessorsAfterInitialization
方法
跟蹤
applyBeanPostProcessorsBeforeInstantiation
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
// 擷取容器中所有BeanPostProcessor, 若BeanPostProcessor 是InstantiationAwareBeanPostProcessor ,則調用其 postProcessBeforeInstantiation 方法
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;
}
applyBeanPostProcessorsBeforeInstantiation
方法内部,首先擷取容器中所有
BeanPostProcessor
,
若
BeanPostProcessor
是
InstantiationAwareBeanPostProcessor
,
則調用其
postProcessBeforeInstantiation
方法 。
然後我們在容器啟動的時候,在容器中注冊了
AnnotationAwareAspectJAutoProxyCreator
并且這個
bean
實作的
InstantiationAwareBeanPostProcessor
接口,是以在容器建立bean的時候,會觸發
AnnotationAwareAspectJAutoProxyCreator
的
applyBeanPostProcessorsBeforeInstantiation
方法。
這個是Spring AOP 的真正入口。
接下來我們詳細分析:
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation
(
AnnotationAwareAspectJAutoProxyCreator
繼承了
AbstractAutoProxyCreator
)
postProcessBeforeInstantiation
調用鍊:
詳細分析:
在postProcessBeforeInstantiation 中查找所有的增強器
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation
的源碼如下,在容器建立任何一個bean的時候觸發:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
//1.先擷取 bean的key
Object cacheKey = getCacheKey(beanClass, beanName);
//2. 判斷bean是否已經處理過,處理過的bean被放入targetSourcedBeans 集合中。
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
//3.判斷是否已經包含bean的增強器
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//4.判斷bean類型 和 是否應該跳過
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass,
beanName, targetSource);
// 建立代理bean
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
1.先擷取 bean的key
2.判斷bean是否已經處理過,處理過的bean被放入targetSourcedBeans 集合中。
3.判斷是否已經包含bean的增強器
4.判斷是否是需要增強的bean
a.判斷bean的類型是否為基礎類:Advice,Pointcut,Advisor,AopInfrastructureBean進入isInfrastructureClass源碼:
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("");
}
return retVal;
}
b.判斷是否跳過處理,進入shouldSkip方法源碼
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 查找容器中所有的候選的增強器清單
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 若清單中包含目前bean的增強器,傳回true
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
跟蹤findCandidateAdvisors 方法内部:
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 容器中所有實作Advisor接口的bean元件,熟悉 Spring 事物的都知道,Advisor接口是為Spring事務服務的
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
// 查找容器是标注@Aspect 元件的bean ,并解析bean的标注 @Before, @After, @AfterReturning, @AfterThrowing 的方法,即查找增強器。并加入緩存中。
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
5.後續第一次執行不到
postProcessAfterInitialization
詳細過程:
跟蹤org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization源碼:
@Override
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;
}
進入wrapIfNecessary方法:
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.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 建立代理對象
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;
}
跟蹤getAdvicesAndAdvisorsForBean()方法最終調用:org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到候選的增強器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 篩選可用的增強器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 擴充
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
跟蹤: findCandidateAdvisors():
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 查找所有 實作Advisor的接口的增強器
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
// 查找所有Aspect ,查找容器是标注@Aspect 元件的bean ,并解析bean的标注 @Before, @After, @AfterReturning, @AfterThrowing 的方法,即查找增強器。并加入緩存中。
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
跟蹤:findAdvisorsThatCanApply 并最終調用:org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
進入 canApply方法: 最終調用:org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean)方法:
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
// 建立方法比對器
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
// 比對切面的方法
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
getAdvicesAndAdvisorsForBean 方法邏輯分析結束。
跟蹤createProxy 方法:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 建立代理工廠
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 設定使用JDK代理還是使用CGLIB代理
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 織入增強器
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 建立代理對象, 代理對象持有 增強器。
return proxyFactory.getProxy(getProxyClassLoader());
}
這樣 postProcessAfterInitialization 的邏輯就分析。
總結
在分析了Spring AOP的啟動過程,總結一下總體過程:
1.setBeanFacotry 接口,在容器啟動的時候,建立了 BeanFactoryAdvisorRetrievalHelperAdapter 增強器探索更具和BeanFactoryAspectJAdvisorsBuilderAdapter 增強器的建構器
2.postProcessBeforeInstantiation 接口: 查找所有的切面和Advisor,并将切面的通知解析,建構成初步的增強器,加入到緩存中來。
3.postProcessAfterInitialization 接口,從緩存取出所有的将所有的增強器,建立代理工廠,并織入增強器,建立代理對象
調用過程:
待更新...