前面通過四篇文章講了代理
包括靜態代理,jdk動態代理,cglib動態代理,jdk與cglib動態代理比較,比較詳細的瞭解了兩者的用法以及源碼,知道了兩者的機制,接下來我們要分析的spring aop 算是一個動態代理的具體例子,實際去看看動態代理是如何使用的
本文的目標
1、spring aop在什麼情況下使用jdk動態代理,什麼時候使用cglib動態代理
2、增強邏輯是如何生成的
例子
注:本文的例子是基於springboot搭建的
pom文件,添加如下依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
目標類Hello
@Component
public class Hello {
public void sayHello(){
System.out.println("hello");
}
}
切面類AspectJTest,主要有前置、後置和環繞通知
@Aspect
@Component
public class AspectJTest {
@Pointcut("execution(* *.sayHello(..))")
public void one(){
}
@Before("one()")
public void beforeHello(){
System.out.println("beforeHello");
}
@After("one()")
public void afterHello(){
System.out.println("afterHello");
}
@Around("one()")
public Object aroundHello(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("beforeHello1");
Object o = joinPoint.proceed();
System.out.println("afterHello1");
return o;
}
}
測試ControllerTest
@Controller
public class ControllerTest {
@Autowired
private Hello hello;
@RequestMapping("/mytest")
@ResponseBody
public String test(){
hello.sayHello();
return "success";
}
}
啓動類
@SpringBootApplication
public class LcnManagerApplication {
public static void main(String[] args) {
SpringApplication.run(LcnManagerApplication.class, args);
}
}
啓動後訪問http://localhost:8080/mytest
打印結果
以上是spring aop 基於註解的寫法
下面我們一步一步去分析
由於我們使用的是spring boot ,僅僅添加了一個starter ,我們查看auto包下的spring.factories 文件發現配置了Aop自動配置類
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
我們的入口就在這個類AopAutoConfiguration,其代碼如下
@Configuration
//我們加入了aop依賴,這幾個類都是存在的
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,
AnnotatedElement.class })
//我們配置文件中沒有配置spring.aop.auto屬性,但是matchIfMissing爲true還是可以加載此配置類的
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = false)
//我們沒有配置spring.aop.proxy-target-class,但是matchIfMissing爲false此配置類不加載
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration {
}
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
//我們沒有配置spring.aop.proxy-target-class,但是matchIfMissing爲true加載此配置類
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
}
這是個配置類,有兩個註解管控次配置類是否生效@ConditionalOnClass與@ConditionalOnProperty
1、@ConditionalOnClass註解表明,只有{EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class
這幾個類都存在的情況下,才能生效,我們再pom文件中加入了aop依賴,這幾個類都是存在的
2、@ConditionalOnProperty註解表明,只有配置文件中存在某個參數,並且匹配上才能加載此類
這裏有幾個參數:
prefix:配置前綴
name:配置名
havingValue:如果name屬性存在,則和此值比較,相同返回true
matchIfMissing:如果配置中沒有指定的name屬性,是否允許加載此配置類,true表示允許,false表示不允許。
eg:我們實際解釋下@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
首先判斷配置文件中是否存在spring.aop.auto屬性,如果存在,其值是否爲havingValue,如果和havingValue一致則加載此配置,如果不一致則不加載;如果配置文件中spring.aop.auto屬性都沒有,則看matchIfMissing屬性的值,如果爲true則加載此配置類,如果爲false則不加載此配置類。
此處兩個註解都是true所以AopAutoConfiguration配置類加載
AopAutoConfiguration加載後,內部有兩個靜態內部類,其主要用於啓用@EnableAspectJAutoProxy註解,區別在於參數proxyTargetClass不一致。
兩個內部類的@ConditionalOnProperty註解參數不一樣,最終加載的是CglibAutoProxyConfiguration 配置,啓動註解@EnableAspectJAutoProxy並且參數proxyTargetClass 爲true。
注:所以我們再使用aop時(springboot),不一定需要顯示的用@EnableAspectJAutoProxy註解
我肯看下@EnableAspectJAutoProxy,代碼如下
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
//是否開啓基於類(cglib)的代理,默認爲false(false表示基於jdk的代理),
boolean proxyTargetClass() default false;
//是否暴露代理,默認爲false
boolean exposeProxy() default false;
}
這個註解有兩個參數,重點關注proxyTargetClass這在我們傳遞的參數是true,所以在spring boot中默認開啓的是基於類的cglib代理模式。
我們繼續看AspectJAutoProxyRegistrar類,主要作用就是根據@EnableAspectJAutoProxy註解,用BeanDefinitionRegistry 註冊AnnotationAwareAspectJAutoProxyCreator類
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
//根據@EnableAspectJAutoProxy的proxytargetclass屬性註冊、升級、配置
//AnnotationAwareAspectJAutoProxyCreator
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//註冊
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);
}
}
}
}
我們一步一步看
1、註冊或升級AnnotationAwareAspectJAutoProxyCreator
通過類的名稱我們可以想象出,此類是代理的創建者,基本上也是這樣aop的實現基本都是靠此類完成的,我們跟進代碼
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
//我們看到註冊的類是AnnotationAwareAspectJAutoProxyCreator
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class,
registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//如果已經註冊過,並且與當前註冊的不一致要根據優先級來確定用哪個
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;
}
//根據AnnotationAwareAspectJAutoProxyCreator構造beandefinition,然後註冊
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
以上代碼重要的就是根據AnnotationAwareAspectJAutoProxyCreator構造beandefinition,然後用BeanDefinitionRegistry 註冊到容器中
2、爲AnnotationAwareAspectJAutoProxyCreator的beandefinition設置proxytargetclass與exposeProxy屬性
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
其實就是set屬性,前面說過了proxytargetclass爲true,exposeProxy爲false
下面開始講解AnnotationAwareAspectJAutoProxyCreator
首先看下AnnotationAwareAspectJAutoProxyCreator類的層次結構
紅色框是自動代理的創建類的繼承邏輯,基本上Aop的操作都在裏面,又實現了接口BeanPostProcessor與接口InstantiationAwareBeanPostProcessor,使得該類在實例化前後與初始化前後做了一些操作(先進行實例化,然後再初始化),這些操作完成了代理生成、增強邏輯的生成等。
實例化前後和初始化前後的方法都在類AbstractAutoProxyCreator中
我們先從postProcessBeforeInstantiation開始,代碼如下
其中advisedBeans是個map,value爲false時表示不需要代理,爲true表示可以代理
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//目標類是否爲基礎設施類,基礎類不代理,或者設定了bean不需要代理。
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;
}
可以看到在實例化之前主要做了兩件事,第一件事判斷當前的bean是否需要代理,代碼如下
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("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 獲取所有增強其,判斷是否需要跳過,一般我們不用
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
//調用父類,這裏直接返回了false
return super.shouldSkip(beanClass, beanName);
}
第二件事,我們自己定義了TargetSource則按我們定義的取創建代理
我們具體的邏輯在這裏沒有看到
接下來是postProcessAfterInstantiation方法,這個方法直接返回true,沒有更過的業務
同樣postProcessBeforeInitialization也沒有做太多的處理直接返回的bean
重要的邏輯都在postProcessAfterInitialization方法中
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
//如果適合被代理,需要封裝
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//targetSourcedBeans存在beanname,即我們定義了自己的targetsource則直接返回
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;
}
// 獲取所有的增強攔截器
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;
}
從上面代碼可以看出,要創建代理需要分爲兩部分
1、獲取增強攔截器
2、根據獲取的增強攔截器去創建代理
我們先看如何獲取增強攔截器的,方法getAdvicesAndAdvisorsForBean
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//獲取所有增強
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
//爲空則返回DO_NOT_PROXY
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//獲取增強
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//獲取當前bean能應用的增強
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
重要的方法是findCandidateAdvisors與findAdvisorsThatCanApply
protected List<Advisor> findCandidateAdvisors() {
// 從父類中加載xml配置形式的aop.
List<Advisor> advisors = super.findCandidateAdvisors();
// 註解方式時,這裏可以獲取bean註解增強.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
其中buildAspectJAdvisors是重點,其對註解的獲取,增強器的獲取都在其中
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
//獲取在容器中的beanname
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
//遍歷所有的beanname
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
//根據beanname獲取beantype
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
//beantype存在Aspect註解
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//解析增強方法
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
//記錄在緩存
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
//組裝返貨
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
可以看到具體的邏輯的
1、首先獲取所有的beanname
2、根據beanname獲取對應的class(beantype)
3、根據class判斷類中是否存在Aspect註解
4、對存在Aspect的類獲取增強器
獲取增強器的方法是getAdvisors,代碼如下
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
//獲取標記了Aspect註解的類
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
//獲取標記了Aspect註解的類名
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
//獲取除標註Pointcut的所有方法
for (Method method : getAdvisorMethods(aspectClass)) {
//獲取增強器
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// 配置了增強延時初始化
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// 獲取DeclareParents註解
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
然後繼續看getAdvisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
//切點信息獲取
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
//根據切點信息生成增強器
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
1、切點信息獲取
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
//獲取方法上的註解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
//封裝
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
//爲ajexp 設置表達式,比如我們這得是one()
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
//只搜索這些註解
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
//獲取指定方法上的註解,並用AspectJAnnotation封裝
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
return new AspectJAnnotation<>(result);
}
else {
return null;
}
}
2、根據切點信息生成增強器
new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName)
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
//真正實例化
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
可以看到封裝只是簡單地賦值
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
//根據不同的註解類型創建不同的增強器
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
從函數中可以看到spring會根據不同的註解生成不同的增強器,對應關係如下
@Around AspectJAroundAdvice
@Before AspectJMethodBeforeAdvice
@After AspectJAfterAdvice
@AfterReturning AspectJAfterReturningAdvice
@AfterThrowing AspectJAfterThrowingAdvice
我們只分析我們例子中用到的
AspectJAroundAdvice代碼如下,可以看到其實現了MethodInterceptor接口,是個標準的增強器
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
//ProceedingJoinPoint 這是@Around註解方法的參數
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
}
protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// 利用反射調用增強方法,這裏的actualArgs就是@Around註解方法的參數ProceedingJoinPoint
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
AspectJAfterAdvice代碼如下,也同樣實現了MethodInterceptor,先去執行目標方法再去執行增強方法
public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
//先去執行目標方法
return mi.proceed();
}
finally {
//再調用增強方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
}
AspectJMethodBeforeAdvice代碼如下,和以上兩種不太一樣這裏沒有實現MethodInterceptor,而是實現了MethodBeforeAdvice該方法只有一個before方法,調用before方法執行增強邏輯
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
但是又是何時調用的before方法呢,其實這裏有個包裝類MethodBeforeAdviceInterceptor代碼如下,實現了MethodInterceptor接口
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
//執行增強
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
//執行目標方法
return mi.proceed();
}
}
可以看到這個類的invoke方法是先執行了增強,然後再執行了目標方法
直到這裏spring 已經把所有的增強器都創建出來了,相當於在前面幾篇文章中我們手寫的幾個類HelloInvocationHandler,CglibProxyIntercepter。
3、根據當前的bean尋找匹配的增強器
在上篇的篇幅我們通過掃描所有的標註了@Aspect的註解的類,解析類中的標註了通知類型的註解,spring通過註解類型創建了不同的增強器,這裏的增強器是整個容器所有的,全部的,還需要爲當前的bean尋找匹配的,比如爲Hello類中的sayHello方法匹配增強器@Around(one())標註的方法,具體做法是拿到你execution(* *.sayHello(..))表達式,去匹配類中的方法匹配返回true
簡單看下代碼
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;
}
4、創建代理
接下來就是要創建代理了
Object proxy =
createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
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
proxyFactory.copyFrom(this);
//如果是jdk代理,判斷是否設置了preserveTargetClass
if (!proxyFactory.isProxyTargetClass()) {
//如果設置了preserveTargetClass爲true,採用cglib代理
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
//否則爲proxyFactory添加接口屬性
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());
}
這裏重點在構建增強器與獲取代理,這裏有個疑問我們不是已經構造了所有的增強器了嗎,爲什麼還有構建?
構建Advisor
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// 獲取註冊的通用攔截器
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
//通過攔截器不爲空
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
//封裝爲Advisors
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
這裏爲什麼還要封裝呢,因爲我們前面分析的增強器,有些是註解式的,有些是從xml加載的,有些可能是Advisor有些可能是advice類型的這裏爲了統一
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
創建代理proxyFactory.getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
這裏通過代理工廠去創建AopProxy的,AopProxy分爲兩種,一種是jdkProxy,一種是cglibproxy,基本上知道點spring的都會知道這個,或者聽說過。什麼 aop 底層用的jdk動態代理啊,什麼時候用cglib代理啊等等
還記得開始的註解參數proxytargetclass 最爲重要,完全控制着用什麼代理
1、如果目標對象實現了接口,默認情況下會使用jdk代理
2、目標類沒有實現接口,則使用cglib動態代理
然後我們看下,兩者創建代理類的步驟是否和咱們前幾篇講的一致
JdkDynamicAopProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
可以看到其創建代理的步驟完全按照jdk創建動態代理的步驟一樣,傳入classloader,實現的接口,和增強邏輯,增強邏輯爲this對象,則表明此類實現了InvocationHandler並實現了invoke方法,事實確實是這樣
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
invoke方法如下
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
//equals方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
//hashcode方法
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 獲取當前方法的攔截器鏈
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
//爲空直接調用目標方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// ReflectiveMethodInvocation封裝攔截器連
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 執行攔截器鏈
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
invoke方法獲取了當前方法的攔截器鏈,然後封裝爲ReflectiveMethodInvocation,通過ReflectiveMethodInvocation的proceed方法進行攔截器鏈(增強鏈)依次調用.
public Object proceed() throws Throwable {
// 如果攔截器鏈已經都執行完則執行目標方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//獲取攔截器中的下一個攔截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//動態匹配
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
//普通攔截器去執行攔截器的invoke方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
這裏的步驟是
1、判斷攔截器是否都執行完,都執行完就去執行目標方法
2、獲取下一個攔截器
3、執行攔截器的invoke方法
CglibAopProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// cglib動態代理最重要的類
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
//獲取所有攔截器
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// 構建代理
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
以上函數完成了Enhancer 的構建,屬性設置,以及代理的創建。其中最重要的是獲取攔截器
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// 用DynamicAdvisedInterceptor封裝advise
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
Callback[] mainCallbacks = new Callback[] {
//加入攔截器數組
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimizations by sending the AOP calls
// direct to the target using the fixed chain for that method.
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
for (int x = 0; x < methods.length; x++) {
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(methods[x].toString(), x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
這裏用DynamicAdvisedInterceptor封裝了advise,作爲Callback 返回,我們知道在cglib設置增強(Callback )的時候是設置的實現了MethodInterceptor接口的增強類,可以看出DynamicAdvisedInterceptor也同樣實現了MethodInterceptor並且有intercept去調用攔截器
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//獲取攔截器鏈
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
//用CglibMethodInvocation封裝攔截器鏈,並執行proceed方法
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
CglibMethodInvocation集成ReflectiveMethodInvocation,proceed方法是一樣的,都是同樣的步驟去調用攔截器-->根據攔截器鏈一個一個去掉用
關於咱們這個例子中是如何執行的呢?
我們的執行結果是這樣的
beforeHello1
beforeHello
hello
afterHello1
afterHello
執行順序是
1、執行@Around 的前環繞
2、執行@Before
3、執行目標方法
4、執行@Around的後環繞
5、執行@After
這裏有個疑問爲什麼不止@before在前,而是@Around的前環繞之前呢?
首先我們對我們的增強器肯定排序了
排序的代碼在ReflectiveAspectJAdvisorFactory#getAdvisors方法中,這在前面已經解析過了
具體的排序是在getAdvisorMethods方法中
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
});
//對方法排序
methods.sort(METHOD_COMPARATOR);
return methods;
}
排序規則
private static final Comparator<Method> METHOD_COMPARATOR;
static {
Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
new InstanceComparator<>(
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
(Converter<Method, Annotation>) method -> {
AspectJAnnotation<?> annotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return (annotation != null ? annotation.getAnnotation() : null);
});
Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
}
可以看到順序是
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
所以優先去執行@Around再去執行@Before再去執行的@After
我們有了執行順序,到底是怎麼執行的呢
先去執行@Around對應的增強類是AspectJAroundAdvice,這個類通過反射去調用了切面類的標註的@Around方法,打印beforeHello1,然後調用ProceedingJoinPoint的proceed方法,這個proceed又會調用下一個攔截器@Before對應的MethodBeforeAdviceInterceptor攔截器,然後MethodBeforeAdviceInterceptor調用AspectJMethodBeforeAdvice的before方法打印beforeHello,然後調用MethodInvocation的proceed方法,又會到下一個攔截器,以此類推完成所有的調用,在中間完成對目標方法的調用,然後完成。
總結:
spring Aop 的代碼看完了,有前面幾篇動態代理的基礎這相對比較好理解,下面梳理下所有的步驟
spring 啓動後去掃描容器中的類,找到帶有註解@Aspect的類,解析標註了@Aspect註解的類,跟不不同的方法註解生成不同的增強器,並且按照特定順序排好序。這些增強器再根據當前的bean找到能適用於當前bean的增強器。然後根據參數proxytargetclass的值來創建代理,創建代理後把增強器鏈花,代理去依次調用。