为什么AOP能生效?是因为我们在配置类上面使用了注解@EnableAspectJAutoProxy,@EnableAspectJAutoProxy导入AspectJAutoProxyRegistrar的同时还注入了AnnotationAwareAspectJAutoProxyCreator。所以我们看AOP的源码要从@EnableAspectJAutoProxy开始。
对象是如何被代理的?或者说代理的过程是怎么样的?
在AnnotationAwareAspectJAutoProxyCreator的后置处理方法中调用AbstractAutoProxyCreator#wrapIfNecessary方法。代理的过程要从这个方法开始看。
本文就是围绕上面2个问题展开的。
鉴于篇幅,AbstractAutoProxyCreator#wrapIfNecessary方法只讲一部分。
SpringAop示例代码
package aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class Aop implements PriorityOrdered {
//指定切入点表达式,拦截那些方法,即为那些类生成代理对象
//@Pointcut("execution(* com.aop.UserDao.save(..))") ..代表所有参数
//@Pointcut("execution(* com.aop.UserDao.*())") 指定所有的方法
//@Pointcut("execution(* com.aop.UserDao.save())") 指定save方法
@Pointcut("execution(* aop.*.*(..))")
public void pointCut(){
}
@Before("pointCut()")
public void Before(){
System.out.println("Before");
}
@After("pointCut()")
public void After(){
System.out.println("After");
}
@AfterThrowing("pointCut()")
public void AfterThrowing(){
System.out.println("AfterThrowing");
}
@AfterReturning("pointCut()")
public void AfterReturning(){
System.out.println("AfterReturning");
}
@Around("pointCut()")
public void Around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Around Before");
joinPoint.proceed();
System.out.println("Around After");
}
@Override
public int getOrder() {
return 1;
}
}
package aop;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
@Component
public class AopLog implements LogService{
public String log() {
System.out.println("----log----");
return "1";
}
@Override
public void print() {
System.out.println("----print----");
}
}
package aop;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
//@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ComponentScan()
public class BeanConfig {
}
package aop;
import org.springframework.stereotype.Component;
@Component
public interface LogService {
void print();
}
package aop;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestAopCondition {
public static void main(String[] args) {
System.out.println(Aop.class.isInterface());
/**
* 创建一个BeanDefinition读取器 根据注解读取
* 创建一个BeanDefinition扫描器 能够扫描一个类或者包 转换成bd
**/
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext();
//注册配置类
context.register(BeanConfig.class);
context.refresh();
//如果使用的是JDK代理 即AopLog有接口 那么使用下面的
LogService aopLog = context.getBean("aopLog", LogService.class);
aopLog.print();
//如果使用的是JDK代理 即AopLog没有接口 那么使用下面的
/*AopLog aopLog = context.getBean("aopLog", AopLog.class);
aopLog.log();
aopLog.print();*/
}
}
@EnableAspectJAutoProxy
会导入AspectJAutoProxyRegistrar
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
//proxyTargetClass:作用是确定代理方式 确定是cglib还是jdk
boolean proxyTargetClass() default false;
//exposeProxy:true 通过ThreadLocal保存当前代理实例
boolean exposeProxy() default false;
}
其中有2个属性。
proxyTargetClass:作用是确定代理方式 确定是cglib还是jdk
exposeProxy:true 通过ThreadLocal保存当前代理实例
1.导入AspectJAutoProxyRegistrar
AspectJAutoProxyRegistrar在哪里被加载的?
AspectJAutoProxyRegistrar被加载的方法:
ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
registrars.forEach((registrar, metadata) ->
//metadata是BeanConfig上的注解
//@EnableAspectJAutoProxy(proxyTargetClass = false)
//@ComponentScan()
//调用AspectJAutoProxyRegistrar的registerBeanDefinitions
registrar.registerBeanDefinitions(metadata, this.registry));
}
2.注入AnnotationAwareAspectJAutoProxyCreator
在AspectJAutoProxyRegistrar的registerBeanDefinitions方法中
AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor。
注册AnnotationAwareAspectJAutoProxyCreator对应的BeanDefinition意味着
在PopulateBean的时候可以被拦截调用。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
//@EnableAspectJAutoProxy(proxyTargetClass = false)
//@ComponentScan()
//importingClassMetadata是BeanConfig上的注解
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
//注入AnnotationAwareAspectJAutoProxyCreator对应的bd
//AnnotationAwareAspectJAutoProxyCreator间接继承了AbstractAutoProxyCreator
//通过AbstractAutoProxyCreator可以创建代理类
//registerAspectJAnnotationAutoProxyCreatorIfNecessary 为什么要这么叫呢
//感觉是如果事务和aop同时存在主要其中一个注册就可以了
//注意:切面注册的是AnnotationAwareAspectJAutoProxyCreator
//事务会注入InfrastructureAdvisorAutoProxyCreator
//如果事务和切面同时存在使用AnnotationAwareAspectJAutoProxyCreator
//return registerOrEscalateApcAsRequired
//(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
//读取BeanConfig上的注解@EnableAspectJAutoProxy属性
AnnotationAttributes enableAspectJAutoProxy
= AnnotationConfigUtils.attributesFor
(importingClassMetadata,
EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
//设置属性proxyTargetClass 这个属性的作用是确定代理方式 确定是cglib还是jdk
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
//exposeProxy的属性的值是true的话
//就通过ThreadLocal保存当前代理实例,可通过以下方法获取到代理
//((UserService)AopContext.currentProxy())
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
调用链路图
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}else {
//设置Spring的上下文组件
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
/***
* BeanPostProcessor 的 before方法
* 1.获取该bean所有的BeanPostProcessor
* 2.依次调用BeanPostProcessor的postProcessBeforeInitialization
*/
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
/***
* 触发init方法
*/
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()) {
/***
* BeanPostProcessor 的 after方法
* 1.获取该bean所有的BeanPostProcessor
* 2.依次调用BeanPostProcessor的postProcessAfterInitialization
* 在这里被代理
* AbstractAutoProxyCreator#postProcessAfterInitialization(Object,String)
*/
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
代理的方法入口:可以看到是在初始化bean(InitializeBean)的时候调用BeanPostProcessor的后置处理方法时,生成的代理对象。
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
//在调用完AnnotationAwareAspectJAutoProxyCreator后 会生成代理对象
/***
AOP切面和事务 的BeanPostProcessors如下
0 = {ApplicationContextAwareProcessor@1068}
1 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@1323}
2 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker@1338}
3 = {AnnotationAwareAspectJAutoProxyCreator@1372}
4 = {CommonAnnotationBeanPostProcessor@1346}
5 = {AutowiredAnnotationBeanPostProcessor@1337}
6 = {ApplicationListenerDetector@1734}
*/
Object current =processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
具体一点就是:AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法。AnnotationAwareAspectJAutoProxyCreator继承自AbstractAutoProxyCreator,这个方法就是父类AbstractAutoProxyCreator
因此我们就从这里开始看起。
1.AbstractAutoProxyCreator#postProcessAfterInitialization
proxyTargetClass=false; optimize=false; opaque=false; exposeProxy=false; frozen=false
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//主要就是调用wrapIfNecessary
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
2.AbstractAutoProxyCreator#wrapIfNecessary
1.findAdvisorBeans即寻找所有类型为Advisor.class或者是Advisor.class的父类的name放入advisorNames
2.遍历advisorNames获取Advisor对应的bean
3.找到了一个Advisor类型是BeanFactoryTransactionAttributeSourceAdvisor放入advisors这个是事务的advisor。
4.使用aspectJAdvisorsBuilder找到所有的Aspect。并解析Aspect下的所有的Advisor放入advisors
5.筛选所有的可应用的Advisors 就是解析切面表达式 判断是否匹配
具体:解析表达式生成匹配器 然后和所有的方法进行匹配只要满足就可以加入eligibleAdvisors
6.在指定下标位置插入一个元素 当前下标元素以后当前下标元素后面的元素往后移动
7.排序
AOP&事务排序前
advisors = {ArrayList@1823} size = 6
0=org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor:advice org.springframework.transaction.interceptor.TransactionInterceptor@2dc54ad4
1 = {InstantiationModelAwarePointcutAdvisorImpl@1832} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.Around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON"
2 = {InstantiationModelAwarePointcutAdvisorImpl@1833} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.Before()]; perClauseKind=SINGLETON"
3 = {InstantiationModelAwarePointcutAdvisorImpl@1831} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.After()]; perClauseKind=SINGLETON"
4 = {InstantiationModelAwarePointcutAdvisorImpl@1830} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.AfterReturning()]; perClauseKind=SINGLETON"
5 = {InstantiationModelAwarePointcutAdvisorImpl@1829} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.AfterThrowing()]; perClauseKind=SINGLETON"
AOP&事务 增加ADVISOR 排序后
eligibleAdvisors = {ArrayList@1823} size = 7
0 = {ExposeInvocationInterceptor$1@1828} "org.springframework.aop.interceptor.ExposeInvocationInterceptor.ADVISOR"
1 = {InstantiationModelAwarePointcutAdvisorImpl@1829} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.AfterThrowing()]; perClauseKind=SINGLETON"
2 = {InstantiationModelAwarePointcutAdvisorImpl@1830} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.AfterReturning()]; perClauseKind=SINGLETON"
3 = {InstantiationModelAwarePointcutAdvisorImpl@1831} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.After()]; perClauseKind=SINGLETON"
4 = {InstantiationModelAwarePointcutAdvisorImpl@1832} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.Around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON"
5 = {InstantiationModelAwarePointcutAdvisorImpl@1833} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.Before()]; perClauseKind=SINGLETON"
6=org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor: advice org.springframework.transaction.interceptor.TransactionInterceptor@2dc54ad4
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//查看advisedBeans集合是否包含这个类的名字,如果包含就直接返回
//advisedBeans 就是一个集合
//用来保存不需要代理的类。比如我们上面定义的切面本身是不需要被代理的。
//还有就是代理过也不需要代理
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//isInfrastructureClass(beanClass)
//判断我们这个业务类是否需要被代理,进入isInfrastructureClass代码
//判断Advice、Pointcut、Advisor是否是beanClass的超类或者超接口
//shouldSkip(beanClass, beanName)
//主要是判断beanName不为空且不是以ORIGINAL结尾
//2个条件都是false 说明需要代理
if (isInfrastructureClass(bean.getClass())
|| shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
/***
获取所有该bean可应用的事务和切面的Advisors
*/
Object[] specificInterceptors =
getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//DO_NOT_PROXY = 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;
}
2.1 isInfrastructureClass:是否需要被代理?
Advice、Pointcut、Advisor等是跟切面相关的,不需要代理
protected boolean isInfrastructureClass(Class<?> beanClass) {
//Advice.class.isAssignableFrom(beanClass)
//判定此 Advice.class 对象所表示的类或接口与指定的 beanClass参数所表示的类或接口是否相同,
//或是否是其超类或超接口。
//Advice、Pointcut、Advisor等是跟切面相关的,不需要代理。 所以这里不会进入判断
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;
}
2.2isOriginalInstance
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL";
static boolean isOriginalInstance(String beanName, Class<?> beanClass) {
//先判断beanClass + ".ORIGINAL" 的长度是否和beanName的长度相等
if (!StringUtils.hasLength(beanName) || beanName.length() !=
beanClass.getName().length() +
AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX.length()) {
return false;
}
//真正判断名称是否相等
return (beanName.startsWith(beanClass.getName())
&& beanName.endsWith(AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX));
}
2.3getAdvicesAndAdvisorsForBean
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
2.3.1findEligibleAdvisors
1.根据类型Advisor查找Advisor类型的bean
2.查找Aspect类型的bean根据Aspect类型解析出来advisors
3.从1 2 返回的集合中筛选可用的Advisor
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//查找候选advisor有2种方式
//方式1:
//先查找所有的类型为Advised的候选Advisors 具体就是根据类型找下面这个代码找
//advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
// this.beanFactory, Advisor.class, true, false);
//方式2:获取所有的ASPECT的bean,解析ASPECT类型的bean为Advisors
//advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
//从所有带有@Aspect注解的bean中解析获取Advisor
//具体一点:判断方法是否有@Pointcut注解:
//排除带有@Pointcut注解的方法。
//依次在剩下的方法上查找AspectJ的六种注解
//分别是@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing
//因为上面已经排除带有@Pointcut的方法 所以只会剩下
//@Around、@Before、@After、@AfterReturning、@AfterThrowing
//将增强方法构建为Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//筛选所有的可应用的Advisors,找到与当前bean相匹配的增强。
//就是解析表达式 判断是否匹配 具体:解析表达式生成匹配器
//具体:
//先用切面表达式做类匹配
//获取pointcut,从方法中取出方法匹配器
//然后和所有的方法进行匹配只要满足就可以加入eligibleAdvisors
//Advisors 和 methods双重循环遍历
List<Advisor> eligibleAdvisors =
findAdvisorsThatCanApply
(candidateAdvisors, beanClass, beanName);
//在指定下标位置插入一个元素 当前下标元素以后当前下标元素后面的元素往后移动
//advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
extendAdvisors(eligibleAdvisors);
//最后排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
2.3.1.1findCandidateAdvisors
@Override
protected List<Advisor> findCandidateAdvisors() {
//查找类型为Advisor
List<Advisor> advisors = super.findCandidateAdvisors();
//解析Aspect切面获取Advisor
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
public List<Advisor> buildAspectJAdvisors() {
//里面只有一个aop
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
//获取所有的bean
String[] beanNames = BeanFactoryUtils
.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
//判断是不是Aspect类 是否有@Aspect注解
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd =
new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind()
== PerClauseKind.SINGLETON) {
//构建解析Aspect的工厂类
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory
(this.beanFactory, beanName);
//解析Aspect下的所有的Advisor 并放入缓存中
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 {
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException();
}
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<>();
//遍历所有的Aspect
for (String aspectName : aspectNames) {
//根据AspectName从缓存中获取对应的List<Advisor> 并加入advisors
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}else {
MetadataAwareAspectInstanceFactory factory
= this.aspectFactoryCache.get(aspectName);
//如果是AspectJAdvisorFactory接口类型的实现类
//直接调用getAdvisors 获取对应的List<Advisor> 加入 advisors
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
我们可以看到,首先第一次调用这个buildAspectJAdvisors()方法时,这个aspectNames一定是个null,接着就会进入到这个if分支的处理中,首先从IOC容器中获取所有的bean,然后遍历依次处理每个bean。
在处理bean的时候,有两步非常重要的操作,
第一步就是通过advisorFactory.isAspect()找到所有加了@Aspect注解的类;
第二步就是通过this.advisorFactory.getAdvisors(factory)进一步找到切面类中的增强方法,并将增强方法构建为Advisor。
看下第二步this.advisorFactory.getAdvisors(factory)是怎么做的?
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
//获取所有的增强方法
for (Method method : getAdvisorMethods(aspectClass)) {
//构建InstantiationModelAwarePointcutAdvisorImpl实例
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);
}
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(
//参数1:aspectClass:@Aspect注解的类
aspectClass,
//参数2:MethodCallback
method -> {
//没有@Pointcut注解的方法 加入methods
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
},
//参数3:MethodFilter
//(method -> !method.isBridge() && !method.isSynthetic() &&
// method.getDeclaringClass() != Object.class);
ReflectionUtils.USER_DECLARED_METHODS);
if (methods.size() > 1) {
methods.sort(METHOD_COMPARATOR);
}
return methods;
}
public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) {
// 获取代理类class的所有的方法
Method[] methods = getDeclaredMethods(clazz);
for (Method method : methods) {
/***
调用!method.isBridge() && !method.isSynthetic()
过滤桥接方法和合成方法
***/
//
if (mf != null && !mf.matches(method)) {
continue;
}
try {
/***
没有@Pointcut注解的方法 加入methods
***/
mc.doWith(method);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException();
}
}
//获取父类中的 方法
if (clazz.getSuperclass() != null) {
doWithMethods(clazz.getSuperclass(), mc, mf);
}
else if (clazz.isInterface()) {
for (Class<?> superIfc : clazz.getInterfaces()) {
doWithMethods(superIfc, mc, mf);
}
}
}
第一个条件:!mf.matches(method);
public static final MethodFilter USER_DECLARED_METHODS
=(method -> !method.isBridge()
&& !method.isSynthetic()
&& method.getDeclaringClass() != Object.class);
直接调用了Method对象的isBridge()方法和isSynthetic()方法来做的过滤,而这个isBridge()方法是用来判断当前方法是否为桥接方法,而isSynthetic()方法是用来判断当前方法是否为合成方法。
关于桥接方法和合成方法算是Java中的一个冷门知识了,简单来说,桥接方法和合成方法是编译器由于内部需要,编译器自己创建出来的方法,而不是我们程序员创建的方法。
!method.isBridge() && !method.isSynthetic() 这行代码在当前方法为非桥接方法且非合成方法时会返回true,说白了就是过滤出我们程序员创建的方法,排除掉那些编译器内部创建的乱七八糟的方法。
第二个条件:mc.doWith(method);
//没有@Pointcut注解的方法 加入methods
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
说白了这个条件就是用来排除掉@Pointcut注解的pointcut() 方法的。
接下来遍历上面返回的非桥接方法和合成方法以及带有@Pointcut的方法再做一次过滤。
找出那些带有增强注解的方法:@Pointcut,@Around, @Before,@After,@AfterReturning,@AfterThrowing
由于@Pointcut修饰的方法已经被排除了所以只有5种增强的方法会被选中。
//获取所有的增强方法
for (Method method : getAdvisorMethods(aspectClass)) {
//构建InstantiationModelAwarePointcutAdvisorImpl实例
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory,
advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
@Override
@Nullable
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;
}
//如果存在增强注解返回InstantiationModelAwarePointcutAdvisorImpl
return new InstantiationModelAwarePointcutAdvisorImpl
(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
2.3.1.1.1查询增强方法
第一步:getPointcut()底层会依次在指定method上查找AspectJ的六种注解,分别是@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing。
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
//获取方法上的增强注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory
.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
//如果增强注解 存在那么解析增强注解上的切面表达式
//@Around("pointCut()")
//@Around("execution(* tyrant.*.log(..))")
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut
(candidateAspectClass, new String[0], new Class<?>[0]);
//为返回的pointCut设置切面表达式
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
具体查找的话就是findAspectJAnnotationOnMethod方法的这行代码:
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz)。
相当于又进行了1次过滤,判断是否是注解增强的方法。
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
//ASPECTJ_ANNOTATION_CLASSES是1个数组
//@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing。
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation<?> foundAnnotation
= findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
2.3.1.1.2为增强方法构建Advisor
首先就是调用getPointcut()方法来获取method上的切点信息AspectJExpressionPointcut。
AspectJExpressionPointcut切点信息包含了增强方法上的增强注解的切面表达式。
接下来为增强方法构建Advisor。构建一个InstantiationModelAwarePointcutAdvisorImpl实例。
最后将这个实例返回。
return new InstantiationModelAwarePointcutAdvisorImpl
//pointcut包含增强方法的切面表达式
(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()) {
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}else {
//走这里
this.pointcut = this.declaredPointcut;
this.lazy = false;
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
这里直接通过构造方法的方式,将增强方法 candidateAdviceMethod 和 切点 expressionPointcut 等关键信息注入到了InstantiationModelAwarePointcutAdvisorImpl类的实例中。
Advisor中包含了增强方法 candidateAdviceMethod 和 切点 expressionPointcut 等关键信息。
接下来是将构建的Advisors放入缓存,这一步不重要。
经过这个findCandidateAdvisors()方法的处理,那么IOC容器中所有的增强都会被放入到advisors集合中,最后作为结果返回也就是说到目前为止:
List<Advisor> candidateAdvisors = findCandidateAdvisors()
这行代码已经执行完毕了。
此时返回的这个candidateAdvisors中就包含了IOC容器中所有切面类中的所有增强Advisor,那此时我们总不能无脑让这些增强都适用于当前bean吧?
这个肯定是不对的,有可能我们这个bean完全都不满足某一个切面类的切点表达式,对吧?
那接下来该怎么做呢?
其实很简单,那就是从所有切面类的所有增强Advisor中,找到与当前bean相匹配的增强Advisors。
也就是执行这行代码:
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)
这个findAdvisorsThatCanApply()方法会使用增强Advisor中的切点表达式与当前bean中的方法做匹配。
从而找到与当前bean匹配的增强Advisor。
2.3.1.2findAdvisorsThatCanApply
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) {
continue;
}
//判断普通增强
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
findAdvisorsThatCanApply()方法的作用,就是用来完成bean和candidateAdvisors之间的匹配的,最后会将bean匹配到的增强advisors作为出参进行返回。
我们可以看到,这里有两块处理逻辑,我们发现这2块逻辑都会往最终结果eligibleAdvisors中添加元素。
其中第一块逻辑,也就是第一个for循环中,是当 candidate instanceof IntroductionAdvisor 为true时,就会调用canApply(candidate, clazz)方法进行匹配
而第二块逻辑,也就是第二个for循环中,是当 candidate instanceof IntroductionAdvisor 为false时,会调用canApply(candidate, clazz, hasIntroductions)方法进行匹配。
增强还有分类?普通增强、引介增强都是什么?
IntroductionAdvisor其实就是一个接口,继承了Advisor接口。
其实这个IntroductionAdvisor代表了一种增强,我们一般称为“引介增强”,这种引介增强控制的是类级别,控制粒度是比较粗的,所以一般我们不常用,其实candidate instanceof IntroductionAdvisor这行代码,说白了就是用来判断candidate是不是引介增强的。
那现在问题来了,这里的candidate,也就是candidateAdvisors数组中的Advisor到底是不是引介增强呢?
说白了就是有没有实现IntroductionAdvisor接口?
没有,因为我们的Advisor其实是InstantiationModelAwarePointcutAdvisorImpl类的一个实例。
因为构建这个Advisor的时候是直接通过InstantiationModelAwarePointcutAdvisorImpl类的构造方法来完成的。
那现在就好办了,我们直接来看下InstantiationModelAwarePointcutAdvisorImpl类的继承关系不就知道了吗?此时InstantiationModelAwarePointcutAdvisorImpl类的继承关系如下图:
我们可以看到,PointcutAdvisor接口(普通增强)和IntroductionAdvisor接口(引介增强)都继承了Advisor接口, 而InstantiationModelAwarePointcutAdvisorImpl类实现的是PointcutAdvisor接口,而不是IntroductionAdvisor接口,也就是说当前这个candidate并不是引介增强,而是一个普通增强。
所以此时candidate instanceof IntroductionAdvisor这行代码会返回false,接着就会执行普通增强的匹配逻辑。所以此时就会来执行这个canApply(candidate, clazz, hasIntroductions)方法了。
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
//如果是引介增强 那么需要对类级别进行匹配
//具体是使用切面表达式
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor)advisor)
.getClassFilter().matches(targetClass);
//如果是普通增强
}else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
return true;
}
}
关于普通增强,这里再补充一点,那就是大家还记得吗?我们在定义切面的时候可是指定了切点表达式的哦,利用切点表达式我们可以匹配到方法级别,由于普通增强控制的粒度更细,所以我们一般会使用这种PointcutAdvisor类型的增强,也就是普通增强。
来跟踪下目标类与切点表达式的匹配过程
接下来,我们就来看下普通增强到底是怎么进行匹配的,此时我们点进去canApply(candidate, clazz, hasIntroductions)方法,就会看到如下代码:
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
//首先进行类级别的匹配
//如果是AOP增强:这个AspectJExpressionPointcut是不是很眼熟
//Advisor pc = AspectJExpressionPointcut
//对应的classfilter是AspectJExpressionPointcut,
//需要先使用切面表达式和类匹配
//如果是事务增强的Advisor pc = StaticMethodMatcherPointcut
//对应的classfilter是ClassFilter.TRUE,直接返回true
//不需要类级别的匹配
//因为
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
//从PointcutAdvisor中拿Pointcut
//从Pointcut拿的方法匹配器
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
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));
//再进行方法级别的匹配
//每一个advisor的匹配器和class的所有方法匹配 只要匹配到就加入eligible集合
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;
}
我们可以看到,这里分别在类级别和方法级别进行匹配,首先会调用pc.getClassFilter().matches(targetClass)进行类级别的匹配,说白了就是使用切点表达式和目标类进行匹配,如果在类级别都不满足切点表达式的话,那么就没必要进一步去匹配方法了。
只有当类级别满足切点表达式之后,才会进行方法级别的匹配,此时就会获取目标类中的方法,然后依次判断每个方法是否与Advisor中的切点表达式正常匹配。如果匹配加入advisor集合。
只要目标类中有一个方法可以和切点表达式匹配上,那么需要将这个Advisor加入eligibleAdvisors。
只要目标类中有一个方法可以和切点表达式匹配上,那么需要将这个Advisor加入eligibleAdvisors。
只要目标类中有一个方法可以和切点表达式匹配上,那么需要将这个Advisor加入eligibleAdvisors。
假设A方法可以和切面表达式匹配那么对应的advisor就会加入eligibleAdvisors集合
所以这就要求我们在调用时,需要再次做精确匹配,因为由方法A筛选符合条件的advisor对于方法B可能不适用。
那么现在的重点,就是目标类方法和切点表达式是怎么进行匹配的?
这一块我们还需要再深入探索一下,此时我们点进去方法来看一下,代码如下
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions):
@Override
public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
obtainPointcutExpression();
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
if (shadowMatch.alwaysMatches()) {
return true;
}
else if (shadowMatch.neverMatches()) {
return false;
}
else {
if (hasIntroductions) {
return true;
}
RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
return (!walker.testsSubtypeSensitiveVars() ||
walker.testTargetInstanceOfResidue(targetClass));
}
}
我们可以看到这里直接调用getTargetShadowMatch(method, targetClass)方法获取了匹配结果shadowMatch,而如果shadowMatch.alwaysMatches()方法的结果为true的话,那么就说明这个类是需要创建代理的。
因此核心匹配的逻辑在这个getTargetShadowMatch(method, targetClass)方法中,那还有啥好说的,我们继续跟进呗,此时我们会看到下面的代码:
private ShadowMatch getTargetShadowMatch(Method method, Class<?> targetClass) {
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
if (targetMethod.getDeclaringClass().isInterface()) {
Set<Class<?>> ifcs = ClassUtils.getAllInterfacesForClassAsSet(targetClass);
if (ifcs.size() > 1) {
try {
Class<?> compositeInterface = ClassUtils.createCompositeInterface(
ClassUtils.toClassArray(ifcs), targetClass.getClassLoader());
targetMethod = ClassUtils.getMostSpecificMethod(targetMethod, compositeInterface);
}
catch (IllegalArgumentException ex) {
}
}
}
return getShadowMatch(targetMethod, method);
}
主要就是调用了另外一个方法getShadowMatch(targetMethod, method)。
那我们继续跟进getShadowMatch(targetMethod, method)方法
private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
// Avoid lock contention for known Methods through concurrent access...
ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);
if (shadowMatch == null) {
synchronized (this.shadowMatchCache) {
// Not found - now check again with full lock...
PointcutExpression fallbackExpression = null;
shadowMatch = this.shadowMatchCache.get(targetMethod);
if (shadowMatch == null) {
Method methodToMatch = targetMethod;
try {
try {
shadowMatch = obtainPointcutExpression()
.matchesMethodExecution(methodToMatch);
}catch (ReflectionWorldException ex) {
try {
fallbackExpression = getFallbackPointcutExpression
(methodToMatch.getDeclaringClass());
if (fallbackExpression != null) {
shadowMatch = fallbackExpression
.matchesMethodExecution(methodToMatch);
}
}catch (ReflectionWorldException ex2) {
fallbackExpression = null;
}
}
if (targetMethod != originalMethod
&& (shadowMatch == null ||(shadowMatch.neverMatches()
&& Proxy.isProxyClass(targetMethod.getDeclaringClass())))) {
methodToMatch = originalMethod;
try {
shadowMatch = obtainPointcutExpression()
.matchesMethodExecution(methodToMatch);
}catch (ReflectionWorldException ex) {
try {
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
if (fallbackExpression != null) {
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
}
}catch (ReflectionWorldException ex2) {
fallbackExpression = null;
}
}
}
}catch (Throwable ex) {
// Possibly AspectJ 1.8.10 encountering an invalid signature
logger.debug("PointcutExpression matching rejected target method", ex);
fallbackExpression = null;
}
if (shadowMatch == null) {
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
}
else if (shadowMatch.maybeMatches() && fallbackExpression != null) {
shadowMatch = new DefensiveShadowMatch(shadowMatch,
fallbackExpression.matchesMethodExecution(methodToMatch));
}
this.shadowMatchCache.put(targetMethod, shadowMatch);
}
}
}
return shadowMatch;
}
此时我们可以看到,刚进来这个方法时,会看一下缓存中有没有shadowMatch,第一次进来的话肯定是没有的,所以就会进来这个if分支的代码,那么此时就会执行非常核心的一块代码,
就是shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch)这行代码。
首先我们来看下这个obtainPointcutExpression()方法是干嘛的,代码如下:
private PointcutExpression obtainPointcutExpression() {
if (getExpression() == null) {
throw new IllegalStateException("");
}
if (this.pointcutExpression == null) {
this.pointcutClassLoader = determinePointcutClassLoader();
this.pointcutExpression =
buildPointcutExpression(this.pointcutClassLoader);
}
return this.pointcutExpression;
}
我们可以看到,原来在这个obtainPointcutExpression()方法中,进行了AspectJ切点表达式的解析,比如我们日志切面类中的切点表达式execution(public * com.ruyuan.aop.service.ProductServiceImpl.*(..)),最后解析完切点表达式之后,会将切点表达式构建为一个PointcutExpressionImpl类的实例,也就是说obtainPointcutExpression()方法返回的其实就是一个PointcutExpressionImpl类的实例。
刚才我们执行到了
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch)
这行代码,现在obtainPointcutExpression()方法返回了一个PointcutExpressionImpl类的实例,那么接下来就会调用PointcutExpressionImpl类的matchesMethodExecution(methodToMatch)来完成切点表达式和目标类的匹配。
正当我们进入PointcutExpressionImpl类一探究竟时,我们发现这个PointcutExpressionImpl类竟然是aspectj包下的类,也就是说方法匹配这块是由aspectj包完成的,而不是Spring来完成的,Spring只是借助了人家aspectj现成的功能罢了。
那么aspectj是在哪里被引入了呢?
其实Spring是在spring-aspects中引入了aspectjweaver的依赖。
AOP代理的创建:aspectj是怎么来完成方法级别精准匹配的?
现在我们知道obtainPointcutExpression()方法返回的是一个PointcutExpressionImpl类的实例,那么接下来就会调用PointcutExpressionImpl类的matchesMethodExecution(methodToMatch)方法,来完成切点表达式和目标类的匹配。
那我们现在就来看下PointcutExpressionImpl类的matchesMethodExecution(methodToMatch)方法吧。
此时我们会看到如下代码:
代码所在类的全限定类名:org.aspectj.weaver.internal.tools.PointcutExpressionImpl
public ShadowMatch matchesMethodExecution(Method aMethod) {
// 从这里进去匹配
ShadowMatch match = matchesExecution(aMethod);
if (MATCH_INFO && match.maybeMatches()) {
System.out.println("MATCHINFO: method execution match on '" + aMethod + "' for '" + this.expression + "': "
+ (match.alwaysMatches() ? "YES" : "MAYBE"));
}
return match;
}
private ShadowMatch matchesExecution(Member aMember) {
// 这行代码可以暂时忽略
Shadow s = ReflectionShadow.makeExecutionShadow(world, aMember, this.matchContext);
// 这里是重点
ShadowMatchImpl sm = getShadowMatch(s);
sm.setSubject(aMember);
sm.setWithinCode(null);
sm.setWithinType(aMember.getDeclaringClass());
return sm;
}
private ShadowMatchImpl getShadowMatch(Shadow forShadow) {
// 切点表达式匹配
org.aspectj.util.FuzzyBoolean match = pointcut.match(forShadow);
// 省略部分代码
return sm;
}
通过上边的代码,我们可以看到在matchesMethodExecution()方法中又调用了matchesExecution(aMethod)方法来完成匹配,而matchesExecution(aMethod)方法中的重点是getShadowMatch(s)方法
在getShadowMatch(s)方法中,调用了pointcut.match(forShadow)完成了切点表达式的匹配,而pointcut.match(forShadow)的代码如下:
代码所在类的全限定类名:org.aspectj.weaver.patterns.Pointcut
public final FuzzyBoolean match(Shadow shadow) {
// 省略部分代码
if (shadow.getKind().isSet(couldMatchKinds())) {
// 这里开始匹配
ret = matchInternal(shadow);
} else {
ret = FuzzyBoolean.NO;
}
// 省略部分代码
return ret;
}
通过上边的代码,我们可以看到,这里又继续调用了matchInternal(shadow)方法完成了匹配,我们继续往下深入,此时matchInternal(shadow)代码如下:
代码所在类的全限定类名:org.aspectj.weaver.patterns.KindedPointcut
@Override
protected FuzzyBoolean matchInternal(Shadow shadow) {
if (shadow.getKind() != kind) {
return FuzzyBoolean.NO;
}
if (shadow.getKind() == Shadow.SynchronizationLock && kind == Shadow.SynchronizationLock) {
return FuzzyBoolean.YES;
}
if (shadow.getKind() == Shadow.SynchronizationUnlock && kind == Shadow.SynchronizationUnlock) {
return FuzzyBoolean.YES;
}
// signature.matches() 签名匹配,核心方法
if (!signature.matches(shadow.getMatchingSignature(),
shadow.getIWorld(), this.kind == Shadow.MethodCall)) {
// 省略部分代码
return FuzzyBoolean.NO;
}
return FuzzyBoolean.YES;
}
通过上边的代码,我们可以看到,在matchInternal()方法刚进来时先做了一些判断,然后接着又调用了signature.matches(),从这个方法的名字来看,是对签名进行匹配,看起来离匹配的核心逻辑已经非常近了,接下来我们点进去看下这个signature.matches()的代码,大家看这里
代码所在类的全限定类名:org.aspectj.weaver.patterns.SignaturePattern
@Override
public boolean matches(Member joinPointSignature, World world, boolean allowBridgeMethods) {
// 省略部分代码
while (candidateMatches.hasNext()) {
JoinPointSignature aSig = candidateMatches.next();
// System.out.println(aSig);
// 精确匹配
FuzzyBoolean matchResult = matchesExactly(aSig, world, allowBridgeMethods, subjectMatch);
if (matchResult.alwaysTrue()) {
return true;
} else if (matchResult.alwaysFalse()) {
return false;
}
// 省略部分代码
}
return false;
}
private FuzzyBoolean matchesExactly(JoinPointSignature aMember, World inAWorld, boolean allowBridgeMethods, boolean subjectMatch) {
// 省略部分代码
FuzzyBoolean matchesIgnoringAnnotations = FuzzyBoolean.YES;
if (kind == Member.STATIC_INITIALIZATION) {
// 静态初始化类型的匹配
matchesIgnoringAnnotations = matchesExactlyStaticInitialization(aMember, inAWorld);
} else if (kind == Member.FIELD) {
// 属性精确匹配
matchesIgnoringAnnotations = matchesExactlyField(aMember, inAWorld);
} else if (kind == Member.METHOD) {
// 方法精确匹配,因为我们就是要匹配方法,所以当然会走这里
matchesIgnoringAnnotations = matchesExactlyMethod(aMember, inAWorld, subjectMatch);
} else if (kind == Member.CONSTRUCTOR) {
// 构造方法精确匹配
matchesIgnoringAnnotations = matchesExactlyConstructor(aMember, inAWorld);
}
if (matchesIgnoringAnnotations.alwaysFalse()) {
return FuzzyBoolean.NO;
}
// 省略部分代码
}
在这个matches()方法中,最最核心的是调用了matchesExactly()方法,从方法名matchesExactly()来看,它的作用就是做精确匹配的。
当我们看到matchesExactly()方法的代码后,我们发现了新大陆,在这个方法中,它进一步区分了当前你要做的是属性的精确匹配,还是方法的精确匹配,又或者是构造方法的精确匹配.
我们现在要做的当然是方法级别的精确匹配啦,所以就会进入if (kind == Member.METHOD)这个if分支,接着就会调用matchesExactlyMethod()方法来完成方法级别的精确匹配。
此时我们迫不及待的点开matchesExactlyMethod()方法,方法中的代码也随之展示在了我们的眼前
代码所在类的全限定类名:org.aspectj.weaver.patterns.SignaturePattern
/**
* Matches on name, declaring type, return type, parameter types, throws types
*/
private FuzzyBoolean matchesExactlyMethod(JoinPointSignature aMethod, World world, boolean subjectMatch) {
// 判断方法参数是够匹配,不匹配返回NO
if (parametersCannotMatch(aMethod)) {
// System.err.println("Parameter types pattern " + parameterTypes + " pcount: " + aMethod.getParameterTypes().length);
return FuzzyBoolean.NO;
}
// OPTIMIZE only for exact match do the pattern match now? Otherwise defer it until other fast checks complete?
// 判断方法名称是够匹配,不匹配返回NO
if (!name.matches(aMethod.getName())) {
return FuzzyBoolean.NO;
}
// Check the throws pattern
// 判断方法抛出异常是够匹配,不匹配返回NO
if (subjectMatch && !throwsPattern.matches(aMethod.getExceptions(), world)) {
return FuzzyBoolean.NO;
}
// '*' trivially matches everything, no need to check further
if (!declaringType.isStar()) {
if (!declaringType.matchesStatically(aMethod.getDeclaringType().resolve(world))) {
return FuzzyBoolean.MAYBE;
}
}
// '*' would match any return value
// 判断返回值类型是够匹配,不匹配返回NO
// 如果切点表达式返回值类型为*,则表示可以匹配任何类型,就没必要进行下边的匹配
// 而如果切点表达式返回值类型不是*,则对返回值类型进行匹配
if (!returnType.isStar()) {
boolean b = returnType.isBangVoid();
if (b) {
String s = aMethod.getReturnType().getSignature();
if (s.length() == 1 && s.charAt(0) == 'V') {
// it is void, so not a match
return FuzzyBoolean.NO;
}
} else {
if (returnType.isVoid()) {
String s = aMethod.getReturnType().getSignature();
if (s.length() != 1 || s.charAt(0) != 'V') {
// it is not void, so not a match
return FuzzyBoolean.NO;
}
} else {
if (!returnType.matchesStatically(aMethod.getReturnType().resolve(world))) {
// looking bad, but there might be parameterization to consider...
if (!returnType.matchesStatically(aMethod.getGenericReturnType().resolve(world))) {
// ok, it's bad.
return FuzzyBoolean.MAYBE;
}
}
}
}
}
// The most simple case: pattern is (..) will match anything
// 如果切点表达式方法参数只配置了一个参数,且这个参数是..
// 那么就表示可以匹配任何参数类型,此时直接返回YES
if (parameterTypes.size() == 1 && parameterTypes.get(0).isEllipsis()) {
return FuzzyBoolean.YES;
}
// 如果切点表达式配置的参数个数和目标方法的参数个数不相等时,那么直接返回NO
if (!parameterTypes.canMatchSignatureWithNParameters(aMethod.getParameterTypes().length)) {
return FuzzyBoolean.NO;
}
// OPTIMIZE both resolution of these types and their annotations should be deferred - just pass down a world and do it lower
// down
// ResolvedType[] resolvedParameters = world.resolve(aMethod.getParameterTypes());
ResolvableTypeList rtl = new ResolvableTypeList(world, aMethod.getParameterTypes());
// Only fetch the parameter annotations if the pointcut is going to be matching on them
// 当方法参数上加了注解时,就需要来匹配参数注解
ResolvedType[][] parameterAnnotationTypes = null;
if (isMatchingParameterAnnotations()) {
parameterAnnotationTypes = aMethod.getParameterAnnotationTypes();
if (parameterAnnotationTypes != null && parameterAnnotationTypes.length == 0) {
parameterAnnotationTypes = null;
}
}
// 对方法参数的类型进行匹配
if (!parameterTypes.matches(rtl, TypePattern.STATIC, parameterAnnotationTypes).alwaysTrue()) {
// It could still be a match based on the generic sig parameter types of a parameterized type
if (!parameterTypes.matches(new ResolvableTypeList(world, aMethod.getGenericParameterTypes()), TypePattern.STATIC,
parameterAnnotationTypes).alwaysTrue()) {
return FuzzyBoolean.MAYBE;
// It could STILL be a match based on the erasure of the parameter types??
// to be determined via test cases...
}
}
// check that varargs specifications match
// 对可变参数的处理,检查可变参数是否匹配
if (!matchesVarArgs(aMethod, world)) {
return FuzzyBoolean.MAYBE;
}
// passed all the guards..
return FuzzyBoolean.YES;
}
aspectj匹配方法的套路,简单说就是,aspectj会根据切点表达式的配置,分别与目标方法的方法参数、方法名字、方法返回参数、方法抛出异常进行匹配,如果都满足的话,那么就表示当前目标方法是满足切点表达式的,也同时说明目标方法所在的类是需要设置代理的!
匹配的时候是一个for循环,也就是目标类会和所有的增强Advisors都匹配一遍,最终将目标类匹配上的增强Advisor给放到这个eligibleAdvisors集合中作为结果返回。
只要目标类中任意一个方法与增强中的切点表达式匹配上,代表当前增强Advisor是适合这个目标类的。
需要加入eligibleAdvisors集合中。
同时也表示这个目标类是需要设置为代理的。
同时我们返回的advisor集合中的实例有2种类型
切面:InstantiationModelAwarePointcutAdvisor
事务:BeanFactoryTransactionAttributeSourceAdvisor
到这里为止,获取目标类匹配的增强逻辑就分析完毕了,下一步就要利用获取到的这些增强来创建动态代理了!
总结:判断是否需要代理,获取可用Advisors
一.获取所有的advisor,方式有2种:
1.根据type
2.从Aspect类中的方法解析:
找到所有的Aspect类,遍历Aspect类所有的方法,过滤掉非合成非桥接方法和非@Pointcut注解修饰的方法。
进一步判断是否是增强方法,如果是说明是符合条件的增强方法,解析增强方法的切面表达式,
并使用切面表达式构建1个AspectJExpressionPointcut返回。
使用增强方法和AspectJExpressionPointcut构建InstantiationModelAwarePointcutAdvisorImpl实例。
二.为代理类选择可用的advisor。
外层for循环advisors{
内层循环代理类所有的方法{
1.先使用advisor的切面表达式和类匹配
2.在使用切面表达式和方法匹配
3.如果有任意一个方法和advisor能匹配上
4.那么这个advisor就是可用的。
5.由于A方法匹配的advisor对于B方法可能不适用!
6.所以在具体代理类的方法调用时,需要做进一步的判断。
}
}