鄂温克族网站建设/北京网站优化排名
文章目录
- AOP原理解析
- 简单案例
- 源码分析
- @EnableAspectJAutoProxy注解
- AspectJAutoProxyRegistrar
- AnnotationAwareAspectJAutoProxyCreator
- 实现了BeanFactoryAware接口
- 实现InstantiationAwareBeanPostProcessor接口
- 创建代理对象分析
- 包装代理对象
- 是否适合被包装
- 什么是基础class
- 解析@Aspect注解标注的类获取增强器
- 找到候选的增强器
- 获取能够使用的增强器
- 创建代理对象
- 代理对象调用目标方法
- 调用原理
- 演示
- 代理对象调用原理分析
- 调用代理对象
- 把增强器转为方法拦截器链
- 总结
AOP原理解析
简单案例
- 一个用于计算的接口
public interface Calculate {int add(int numa, int numb);int reduce(int numa, int numb);int div(int numa, int numb);int multi(int numa, int numb);
}
- 实现类
public class SimpleCalculate implements Calculate {@Overridepublic int add(int numa, int numb) {return numa + numb;}@Overridepublic int reduce(int numa, int numb) {return numa - numb;}@Overridepublic int div(int numa, int numb) {return numa / numb;}@Overridepublic int multi(int numa, int numb) {return numa * numb;}
}
- 对这个类进行aop编程的切面
@Aspect
public class LogAspect {@Pointcut("execution(* org.apdoer.spring.aop.SimpleCalculate.*(..))")public void pointcut(){}@Before(value = "pointcut()")public void beforeAdvice(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("执行目标方法=="+methodName+"之前执行前置通知,参数"+ Arrays.asList(joinPoint.getArgs()));}@After(value = "pointcut()")public void afterAdvice(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("执行目标方法=="+methodName+"之后执行后置通知,参数"+ Arrays.asList(joinPoint.getArgs()));}@AfterReturning(value = "pointcut()")public void returningAdvice(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("执行目标方法=="+methodName+"之前执行返回通知,参数"+ Arrays.asList(joinPoint.getArgs()));}@AfterThrowing(value = "pointcut()")public void afterThrowingAdvice(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("执行目标方法=="+methodName+"之前执行异常通知,参数"+ Arrays.asList(joinPoint.getArgs()));}
}
需要注意的是aspect
不是spring
的包,需要引入如下依赖
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
- 配置类
@Configuration
@EnableAspectJAutoProxy
public class TestAopConfig {@Beanpublic Calculate calculate() {return new SimpleCalculate();}@Beanpublic LogAspect logAspect() {return new LogAspect();}
}
- 测试类
public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestAopConfig.class);Calculate calculate = (Calculate) applicationContext.getBean("calculate");System.out.println(calculate.add(1, 2));}
}
这里就不一一测试了
源码分析
刚才可以看到在配置类上加了一个@EnableAspectJAutoProxy
注解,这个注解是干什么用的
@EnableAspectJAutoProxy注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {boolean proxyTargetClass() default false;boolean exposeProxy() default false;
}
- 这个类上有个
@Import
注解,这个注解可以给容器中添加组件 - 这个注解有两个属性值
proxyTargetClass
:用于配置代理的方式,true
代表使用cglib
代替jdk
的动态代理exposeProxy
:是否将代理对象通过ThreadLocal
暴露到aop
上下文缓存中,如果暴露,我们可以在上下文中直接获取到,这里可以用来解决同类调用aop
不生效的问题
springboot
也是这个原理,不过是通过SPI
机制自动装配,所以只要有了Aspectj
的依赖就可以
AspectJAutoProxyRegistrar
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//向容器中注册对应的aspectj注解自动代理创建器AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);AnnotationAttributes enableAspectJAutoProxy =AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);if (enableAspectJAutoProxy != null) {if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}}}
}
AspectJAutoProxyRegistrar
实现了ImportBeanDefinitionRegistrar
向我们的容器中注册了一个AnnotationAwareAspectJAutoProxyCreator
注册beanDefinition
就没必要点进去看了,具体在AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
这一行代码中
重点是AnnotationAwareAspectJAutoProxyCreator
这个代理创建器是什么
AnnotationAwareAspectJAutoProxyCreator
以上是这个代理创建器的类图,有几点值得关注
- 实现了
BeanFactoryAware
接口,可以将BeanFactory
绑定到组件上,通过beanFactory
获取容器内的bean
- 还实现了
InstantiationAwareBeanPostProcessor
接口,也是一种后置处理器,可以在bean
实例化前后执行一些操作
下面分别说明各自的作用
实现了BeanFactoryAware接口
AbstractAdvisorAutoProxyCreator
覆盖了AbstractAutoProxyCreator
的setBeanFactory
方法做了两件事
- 调用父类的
setBeanFactory
方法 - 调用
initBeanFactory
初始化BeanFactory
,但是被子类覆盖,最终调用如下
@Overrideprotected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {super.initBeanFactory(beanFactory);//若 apsectj的增强器工厂对象为空,我们就创建一个ReflectiveAspectJAdvisorFactoryif (this.aspectJAdvisorFactory == null) {this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);}//不为空 我们就把aspectJAdvisorFactory 包装为BeanFactoryAspectJAdvisorsBuilderAdapterthis.aspectJAdvisorsBuilder =new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);}
所以, 实现BeanFactoryAware
接口的作用就是
- 将
BeanFactory
绑定到照这个AnnotationAwareAspectJAutoProxyCreator
组件上 - 为
AnnotationAwareAspectJAutoProxyCreator
的aspectJAdvisorsBuilder
赋值 - 能够通过
beanFactory
拿到增强器
实现InstantiationAwareBeanPostProcessor接口
bean
初始化之前
@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {Object cacheKey = getCacheKey(beanClass, beanName);// 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);Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}return null;}
这里面的逻辑如下
- 判断缓存中是否包含当前
bean
,如果不包含,继续判断是否是已经代理的bean- 代理过,不处理
- 没代理过,判断当前
bean
是否是系统bean
,或者是切面逻辑不会包含的bean
,如果是缓存起来
- 经过这一步处理后, 只有在
targetSource
中没有进行缓存,并且应该被切面逻辑包含,但是还未生成代理对象的bean
才会通过此方法
bean
初始化之后
@Overridepublic Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (this.earlyProxyReferences.remove(cacheKey) != bean) {//如果当前的对象适合被包装称为代理bean就进行处理return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}
上面的wrapIfNecessary
包装bean
就是真正的创建代理对象逻辑
创建代理对象分析
包装代理对象
是否适合被包装
前面说到会判断是否适合被包装成为代理bean
,那么是怎么判断呢
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {//1.已经处理的不再处理if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}//2.不需要被增强的直接返回if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}//3.判断当前bean是不是基础类型的bean,或者指定类型的bean 不需要代理if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// 4.如果有增强器,创建代理对象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;}
以上的代码逻辑注释中有写
- 已经处理的不再处理
- 不需要被增强的直接返回
- 判断当前
bean
是不是基础类型的bean
,或者指定类型的bean
不需要代理 - 如果有增强器,创建代理对象
什么是基础class
前面判断是否适合被包装提到基础对象
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;}
其实就是判断当前的class
是不是 Pointcut
Advisor
Advice
AopInfrastructureBean
其中的一种
解析@Aspect注解标注的类获取增强器
@Override@Nullableprotected 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();}
调用了找到合格的增强器
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;}
这里面包含几步
- 找到候选的增强器
- 找到可以使用的增强器
找到候选的增强器
@Overrideprotected List<Advisor> findCandidateAdvisors() {// Add all the Spring advisors found according to superclass rules.List<Advisor> advisors = super.findCandidateAdvisors();// Build Advisors for all AspectJ aspects in the bean factory.if (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;}
这段代码做了两件事
- 从
ioc
容器中获取所有增强器 - 在
beanfactory
中给所有aspectj
切面配置增强器
- 从ioc容器中获取所有增强器
public List<Advisor> findAdvisorBeans() {//1.先从缓存中获取增强器 cachedAdvisorBeanNames是advisor的名称String[] advisorNames = this.cachedAdvisorBeanNames;if (advisorNames == null) {// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the auto-proxy creator apply to them!advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);this.cachedAdvisorBeanNames = advisorNames;}if (advisorNames.length == 0) {return new ArrayList<>();}List<Advisor> advisors = new ArrayList<>();for (String name : advisorNames) {if (isEligibleBean(name)) {//忽略正在创建的增强器if (this.beanFactory.isCurrentlyInCreation(name)) {if (logger.isTraceEnabled()) {logger.trace("Skipping currently created advisor '" + name + "'");}}else {try {//通过getBean的形式创建增强器 //并且将bean 添加到advisors中advisors.add(this.beanFactory.getBean(name, Advisor.class));}}}}return advisors;}
这段代码的逻辑很简单,如注释
- 为
beanfactory
中所有的aspectj
切面配置增强器
public List<Advisor> buildAspectJAdvisors() {//1.先从缓存中获取增强器对象List<String> aspectNames = this.aspectBeanNames;//缓存中没有获取到if (aspectNames == null) {synchronized (this) {//在尝试从缓存中获取一次aspectNames = this.aspectBeanNames;//还是没有获取到if (aspectNames == null) {//2.从容器中获取所有的bean的name List<Advisor> advisors = new LinkedList<Advisor>();aspectNames = new LinkedList<String>();String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);//2.遍历beanNames ,检查对应的bean是否包含有Aspect注解 for (String beanName : beanNames) {if (!isEligibleBean(beanName)) {continue;}//根据beanName获取bean的类型Class<?> beanType = this.beanFactory.getType(beanName);if (beanType == null) {continue;}//检查beanType是否包含Aspectif (this.advisorFactory.isAspect(beanType)) {aspectNames.add(beanName);//创建一个Aspect类的源信息对象AspectMetadata amd = new AspectMetadata(beanType, beanName);if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {MetadataAwareAspectInstanceFactory factory =new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);//3.从aspectj切面中获取通知器,即我们配置的前置通知,后置通知...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;}}}//缓存中有增强器,我们从缓存中获取返回出去List<Advisor> advisors = new LinkedList<Advisor>();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;}
以上就是解析@Aspect
注解,获取增强器
- 先从缓存中获取增强器对象
- 如果缓存没有,就获取容器中所有的
beanname
,依次判断对应的bean
是否是一个被@Aspect
注解标注的类 - 如果是,调用
advisorFactory.getAdvisors
获取通知器
至于通过被@Aspect
注解标注的类来获取通知器,也可以稍微看一下
@Overridepublic List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {//1.获取标识了@Aspect注解的切面类Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();//2.获取切面的名称String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();//3.验证切面类validate(aspectClass);...List<Advisor> advisors = new ArrayList<>();//4.获取切面类中除开@PointCut注解标注的其他所有方法for (Method method : getAdvisorMethods(aspectClass)) {//5.给每个方法获取增强Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);if (advisor != null) {advisors.add(advisor);}}...return advisors;}
这段代码的意思就是
- 获取切面类
- 为切面类中除开
@PointCut
注解标记的其他所有方法获取增强
那么是怎么为方法获取增强的呢
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,int declarationOrderInAspect, String aspectName) {//1.获取切点表达式AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());if (expressionPointcut == null) {return null;}//2.创建增强实现类return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,this, aspectInstanceFactory, declarationOrderInAspect, aspectName);}
再看看切点表达式的获取
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {//1.获取切面注解 @Before @After...AspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);if (aspectJAnnotation == null) {return null;}//2.获取切点表达式对象AspectJExpressionPointcut ajexp =new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);ajexp.setExpression(aspectJAnnotation.getPointcutExpression());if (this.beanFactory != null) {ajexp.setBeanFactory(this.beanFactory);}return ajexp;}
切面注解的获取,不用看都能猜得到,就看方法是是否有那几个注解呗
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {// ASPECTJ_ANNOTATION_CLASSES就是 {Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class}for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);if (foundAnnotation != null) {return foundAnnotation;}}return null;}
再回到前面的为方法获取增强,获取切点表达式后的创建增强实现类
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {...if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {...}else {// A singleton aspect.this.pointcut = this.declaredPointcut;this.lazy = false;//实例化切面this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);}}
这一步把切点,候选的方法…统一处理生成一个增强器
实例化切面是怎么做的
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {//1.获取候选切面Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();//2.获取切面注解AspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);...AbstractAspectJAdvice springAdvice;//3.判断注解类型switch (aspectJAnnotation.getAnnotationType()) {//3.1如果是切点,返回nullcase AtPointcut:if (logger.isDebugEnabled()) {logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");}return null;//3.2 环绕通知case AtAround:springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;//3.3 前置通知case AtBefore:springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;//3.4后置通知case AtAfter:springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;//3.5返回通知case AtAfterReturning:springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterReturningAnnotation.returning())) {springAdvice.setReturningName(afterReturningAnnotation.returning());}break;//3.6异常通知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);//4.获取方法的参数列表,设置到切面方法上去String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);if (argNames != null) {springAdvice.setArgumentNamesFromStringArray(argNames);}springAdvice.calculateArgumentBindings();return springAdvice;}
获取能够使用的增强器
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {ProxyCreationContext.setCurrentProxiedBeanName(beanName);try {return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);}finally {ProxyCreationContext.setCurrentProxiedBeanName(null);}}
调用到AopUtils.findAdvisorsThatCanApply
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {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 processedcontinue;}if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}
找的逻辑相对简单,怎么判断这个canApply
呢
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 {// It doesn't have a pointcut so we assume it applies.return true;}}
还调用了一个canApply
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {//1.创建方法匹配器MethodMatcher methodMatcher = pc.getMethodMatcher();if (methodMatcher == MethodMatcher.TRUE) {// No need to iterate the methods if we're matching any method anyway...return true;}//2.包装方法匹配器IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;}//3.获取类和接口Set<Class<?>> classes = new LinkedHashSet<>();if (!Proxy.isProxyClass(targetClass)) {classes.add(ClassUtils.getUserClass(targetClass));}classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));//4.获取每个类对应的所有方法进行匹配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;}
创建代理对象
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {//1.判断容器类型if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);}//2.创建代理工厂ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);//3.配置代理方式.默认是false.jdk动态代理if (!proxyFactory.isProxyTargetClass()) {if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {//检查beanclass是否实现了接口,未实现接口,为trueevaluateProxyInterfaces(beanClass, proxyFactory);}}//4.获取容器中的方法增强器Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}//5.创建代理对象return proxyFactory.getProxy(getProxyClassLoader());}
到了真正的创建代理对象了
@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (!IN_NATIVE_IMAGE &&(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.");}//实现了接口,用jdk动态代理if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}
在没有显示配置的情况下,如果实现了接口,则使用jdk
动态代理
public Object getProxy(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);//创建jdk代理对象return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}
创建代理对象的流程
- 判断容器类型
- 获取代理工厂
- 设置代理方式
- 获取容器中的方法增强
- 创建代理对象
代理对象调用目标方法
调用原理
当我们在一个类中调用同类注解方法,获取其他方法,默认是采用本类对象调用,所有注解都会失效.
@EnableAspectJAutoProxy(exposeProxy = true)
这个表示是否暴露代理对象
如果配置了为true
,代理对象将会被放到线程变量中,通过aop
上下文可以获取到进行调用
int retVal = ((Calculate) AopContext.currentProxy()).add(numa,numb);
演示
在前面的实现类中新增方法
public int mod(int numa,int numb){int retVal = ((Calculate) AopContext.currentProxy()).add(numa,numb);//int retVal = this.add(numa,numb);return retVal%numa;}
代理对象调用原理分析
调用代理对象
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;TargetSource targetSource = this.advised.targetSource;Object target = null;try {Object retVal;//1.是否暴露代理对象if (this.advised.exposeProxy) {// 把代理 对象放到ThreadLocal中oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}//2.获取被代理对象target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);// 3.获取方法拦截器链(把增强器转换成方法拦截器链)List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);//4.如果没有方法拦截器链,通过反射直接调用if (chain.isEmpty()) {Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);}else {// We need to create a method invocation...MethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// 把方法调用放到方法拦截器链中retVal = invocation.proceed();}// 处理返回类型Class<?> returnType = method.getReturnType();if (retVal != null && retVal == target &&returnType != Object.class && returnType.isInstance(proxy) &&!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {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 {...}}
调用代理对象的逻辑
- 获取代理对象,设置是否需要暴露代理对象
- 获取方法拦截器链,创建方法调用执行(有缓存)
- 处理返回类型
把增强器转为方法拦截器链
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {//1.从缓存中获取,第一次肯定没有MethodCacheKey cacheKey = new MethodCacheKey(method);List<Object> cached = this.methodCache.get(cacheKey);if (cached == null) {//2.获取所有的拦截器cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);//3.放入缓存this.methodCache.put(cacheKey, cached);}return cached;}
真正的获取拦截器链
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {List<Object> interceptorList = new ArrayList<>(advisors.length);Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());Boolean hasIntroductions = null;//遍历所有增强器集合for (Advisor advisor : advisors) {//判断增强器是不是PointcutAdvisorif (advisor instanceof PointcutAdvisor) {PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;//通过方法匹配器进行匹配if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();boolean match;if (mm instanceof IntroductionAwareMethodMatcher) {if (hasIntroductions == null) {hasIntroductions = hasMatchingIntroductions(advisors, actualClass);}match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);}else {match = mm.matches(method, actualClass);}//匹配到,就把增强器转换成拦截器链if (match) {MethodInterceptor[] interceptors = registry.getInterceptors(advisor);if (mm.isRuntime()) {for (MethodInterceptor interceptor : interceptors) {interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));}}else {interceptorList.addAll(Arrays.asList(interceptors));}}}}...}return interceptorList;}
获取方法拦截器链的逻辑
- 获取所有的增强器
- 通过方法匹配器遍历匹配,如果匹配到,就把增强器转换成拦截器链
总结
@EnableAspectJAutoProxy
注解通过ImportBeanDefinitionRegistrar
的方式向容器中注册了AspectJAutoProxyRegistrar
组件- 这个组件实现了
BeanPostProcessor
接口,作为一个bean
的后置处理器,能在bean
的实例化前后处理一些工作 - 在
bean
实例化之后,会去判断当前是不是Pointcut
Advisor
Advice
AopInfrastructureBean
其中的一种,即不需要代理的对象 - 解析被
@Aspect
注解标注的类,获取可用的增强器 - 有增强器就去创建代理对象
- 调用的时候,获取被代理对象的方法,把增强器转换成方法拦截器链,把方法调用放到方法拦截器链中,从而达到面向切面编程