往期博客
《Spring源码深度解析 郝佳 第2版》容器的基本实现与XML文件的加载
《Spring源码深度解析 郝佳 第2版》XML标签的解析
《Spring源码深度解析 郝佳 第2版》bean的加载、循环依赖的解决
《Spring源码深度解析 郝佳 第2版》ApplicationContext
AOP面向切面编程,是一种思想,不同于OOP,他可以为不具有继承关系的对象引入一个公共行为如日志,安全监测等。具体实现分为两种
- Spring AOP:动态代理,运行时生成代理对象。他的方便在于Spring帮助我们完成增强的自动织入,在Java中可以根据接口使用JDK动态代理和Cglib动态代理。由Spring自动为我们完成运行时织入。
- AspectJ:静态代理,编译时直接修改字节码,AspectJ是一套独立的面向切面编程的解决方案。它基于ASM字节码编辑技术,在不使用Spring的时候也可单独使用,需要导入对应的aspect相应的jar包,然后编写静态增强逻辑之后,
- 编译时织入:利用ajc编译器替代javac编译器,直接将源文件(java或者aspect文件)编译成class文件并将切面织入进代码。
- 编译后织入:利用ajc编译器向javac编译期编译后的class文件或jar文件织入切面代码。
- 加载时织入(LTW):不使用ajc编译器,利用aspectjweaver.jar工具,使用java agent代理在类加载期将切面织入进代码。这和之前的二进制编织完全一样,所不同的是织入会被延后,直到类加载器将类加载到JVM。
Spring AOP 与ApectJ 的目的一致,都是为了统一处理横切业务,但与AspectJ不同的是,Spring AOP并不尝试提供完整的AOP功能(即使它完全可以实现),Spring AOP 更注重的是与Spring IOC容器的结合,并结合该优势来解决横切业务的问题,因此在AOP的功能完善方面,相对来说AspectJ具有更大的优势,同时,Spring注意到AspectJ在AOP的实现方式上依赖于特殊编译器(ajc编译器),因此Spring很机智回避了这点,转向采用动态代理技术的实现原理来构建Spring AOP的内部机制(动态织入),这是与AspectJ(静态织入)最根本的区别。
在AspectJ1.5后,引入@Aspect形式的注解风格的开发,Spring也非常快地跟进了这种方式,因此Spring 2.0后便使用了与AspectJ一样的注解。请注意,Spring 只是使用了与 AspectJ 5 一样的注解,但仍然没有使用 AspectJ 的编译器,底层依是动态代理技术的实现,因此并不依赖于 AspectJ 的编译器,因此无论是使用spring aop还是 aspectj都需要aspectjweaver.jar spring-aop.jar这两个jar包。使用AspectJ 的 动态织入LTW 还 需要额外的jar包 spring-instrument.jar。
在Spring中使用Spring AOP本质还是动态代理:
- 创建用于拦截的bean
- 创建Advisor:使用@AspectJ注解定义切面,
@Pointcut("execution(* *.xxx(..))") 声明切点,@Before 、@After 、@Around 等注解声明增强逻辑 - 创建配置文件:在xml配置文件加上
<aop:aspectj-autoproxy> 和待拦截的bean、切面bean - 测试
在SpringBoot中使用 Spring AOP步骤:https://cloud.tencent.com/developer/article/1690944
目录
-
<aop:aspectj-autoproxy> 标签
- AopNamespaceHandler的init方法注册AspectJAutoProxyBeanDefinitionParser实现AOP
- AspectJAutoProxyBeanDefinitionParser解析器的parse方法注册AnnotationAwareAspectJAutoProxyCreator解析器的BeanDefinition实现AOP,并设置target-proxy-class和expose-proxy属性值到BeanDefinition中
-
AnnotationAwareAspectJAutoProxyCreator解析@AspectJ注解标识的Advisor
- Spring AOP的时机
- AbstractAutoProxyCreator核心实现AOP
- wrapIfNessary方法
- createProxy方法
- JdkDynamicAopProxy分析
- Cglib2AopProxy分析
-
AspectJ AOP
一、<aop:aspectj-autoproxy> 标签
只要是声明的自定义注解,一定在需要一个他的解析器,解析器名称一般为XxxNamespaceHandler,在AopNamespaceHandler可以看到 设置对@AspectJ注解的解析器AspectJAutoProxyBeanDefinitionParser
public class AopNamespaceHandler extends NamespaceHandlerSupport {
public AopNamespaceHandler() {
}
public void init() {
this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
1.注册AspectJAutoProxyBeanDefinitionParser
所有的解析器都是对BeanDefinitionParser接口的统一实现,入口都是parse()方法,然后调用registerAspectJAnnotationAutoProxyCreatorIfNecessary() 注册 AnnotationAwareAspectJAutoProxyCreator 解析器的beanDefinition 用于实现AOP
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
this.extendBeanDefinition(element, parserContext);
return null;
}
private void extendBeanDefinition(Element element, ParserContext parserContext) {
BeanDefinition beanDef = parserContext.getRegistry().getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
if (element.hasChildNodes()) {
this.addIncludePatterns(element, parserContext, beanDef);
}
}
2. 注册AnnotationAwareAspectJAutoProxyCreator实现AOP
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
// 2.1 注册升级AnnotationAwareAspectJAutoProxyCreator
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
} else {
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", -2147483648);
beanDefinition.setRole(2);
registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
return beanDefinition;
}
}
// 2.2. 对proxy-target-class以及expose-proxy属性设置到BeanDefinition
在xml配置文件中对<aop:aspectj-autoproxy proxy-target-class = "true" expose-proxy = "true"> 或者<aop:config proxy-target-class = "true" expose-proxy = "true"> ... <aop:config> ,此处就是解析并给beanDefinition设置两个属性
- proxy-target-class:默认Spring AOP使用JDK动态代理,给此属性设置为true表示强制使用Cglib动态代理,需要注意使用Cglib时候不能对final修饰的类代理和需要将Cglib的二进制包放在classpath下面
- expose-proxy:主要是暴露动态代理上下文AopContext,使用AopContext.currentProxy()获得当前代理,以便解决同类内调用方法不走代理的情况(具体事例就是@Transcation注解使用时的一种情况)
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute("proxy-target-class"));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute("expose-proxy"));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition definition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition definition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
二、AnnotationAwareAspectJAutoProxyCreator解析@AspectJ
1. Spring AOP的时机
// 不存在循环依赖AOP的时机postProcessAfterInitialization()
AnnotationAwareAspectJAutoProxyCreator实现AbstractAutoProxyCreatorlei完成AOP的核心功能。
他实现BeanProcessor接口,因此无循环依赖的情况下对Bean的具体AOP的逻辑在父类AbstractAutoProxyCreator的postProcessAfterInitalization() 方法中
// 存在循环依赖AOP时机getEarlyBeanReference()
首先需要明白解决单例bean循环依赖的关键就是在三级缓存中暴露ObjectFactory
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
有循环依赖的情况并且A不需要AOP增强的情况,如A和B互相依赖,并且都是单例的,会使用三级缓存解决循环依赖,大致过程
-
A在实例化完成之后会进行属性填充,此时会将ObjectFactory放到三级缓存,然后进行populateBean()、initializationBean()、postProcessAfterInitialization()等。 -
A在populateBean()时发现A依赖B,就会转去B的getBean()…然后就是B的一系列流程…直到B需要populateBean()的时候发现需要A,会从三级缓存中的ObjectFactory实际调用AbstractAutoProxyCreator重写的getEarlyBeanReference() 拿到半实例的A,假如A不需要AOP,那么完全没问题在getEarlyBeanReference()直接返回A即可,B此时就会拿到半实例不需要增强的A完成初始化,然后初始化好的B被移动到一级缓存 -
然后转回A的populateBean(),在一级缓存中拿到初始化好的B,然后完成后续初始化。
但是有循环依赖并且A需要AOP增强的时候,发挥关键的就是暴露在三级缓存中的getEarlyBeanReference() 了。
-
主要逻辑在AbstractAutoProxyCreator重写的getEarlyBeanReference() ,当B需要从三级缓存中拿到半实例的A时候,这个时候getEarlyBeanReference() 就会被调用,会判断A是否需要增强。 -
当A需要增强,此时B需要填充A增强的代理对象,那么AOP的时机不能像往常一样放到postProcessAfterInitiallization() 中了,而是在这里直接进行AOP返回给B的是A的增强代理实例,然后放到earlyProxyReferences, 标记这个bean已经被early处理过了,避免在postProcessAfterInitiallization() 中重复处理
回顾往期博客《Spring源码深度解析 郝佳 第2版》bean的加载、循环依赖的解决,会发现如果B想要从三级缓存拿到代理的A,会调用getEarlyBeanReference()会进入SmartInstantiantionAwareBeanPostProcess的getEarlyBeanReference() ,然后返回exposedObject并移动到二级缓存。就是在这里完成的提前AOP。 而看关键SmartInstantiationAwareBeanPostProcess的getEarlyBeanReference() 核心实现
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
return bean;
}
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
于是有转到和AbstractAutoProxyCreator类
2. AbstractAutoProxyCreator核心类实现AOP
// 提前AOP的情况
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap(16);
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
// 正常AOP的情况
@Nullable
private BeanFactory beanFactory;
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap(256);
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
// 2. wrapIfNecessary
如果适合被代理,需要封装成指定bean,放到adviserBeans
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
// 2.1 getAdvicesAndAdvisorsForBean
解析增强方法,如@AspectJ注解配置的切面、通知,然后找到该bean能运用的增强
- // 找出所有的增强方法放到List
- // 找出针对该bean的增强方法放到List
@Nullable
protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> var1, String var2, @Nullable TargetSource var3) throws BeansException;
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);
return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
this.extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
// 2.1.1查找所有的增强方法,因为分析的使用注解@AspectJ配置的AOP, 因此查找方法其实是子类AnnotationAwareAspectJAutoProxyCreator类
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
protected List<Advisor> findCandidateAdvisors() {
List<Advisor> advisors = super.findCandidateAdvisors();
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
// 核心实现 BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors()
- 获取所有注册在beanFactory的beanName
- 遍历所有beanName,找出@AspectJ标注的类,然后 就是最复杂的地方,委托给AspectJAdvisorFactory接口的实现类ReflectiveAspectJAdvisorFactory的getAdvisors方法
- 对于切面类增强方法提取
- 将提取结果加入缓存
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();
List<String> aspectNames = new ArrayList();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
String[] var18 = beanNames;
int var19 = beanNames.length;
for(int var7 = 0; var7 < var19; ++var7) {
String beanName = var18[var7];
if (this.isEligibleBean(beanName)) {
Class<?> beanType = this.beanFactory.getType(beanName, false);
if (beanType != null && 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 {
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();
} else {
List<Advisor> advisors = new ArrayList();
Iterator var3 = aspectNames.iterator();
while(var3.hasNext()) {
String aspectName = (String)var3.next();
List<Advisor> cachedAdvisors = (List)this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
} else {
MetadataAwareAspectInstanceFactory factory = (MetadataAwareAspectInstanceFactory)this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
}
// 获取切面的增强方法是最复杂的地方,委托给AspectJAdvisorFactory接口的实现类ReflectiveAspectJAdvisorFactory的getAdvisors方法
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
this.validate(aspectClass);
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList();
Iterator var6 = this.getAdvisorMethods(aspectClass).iterator();
while(var6.hasNext()) {
Method method = (Method)var6.next();
Advisor advisor = this.getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
Field[] var12 = aspectClass.getDeclaredFields();
int var13 = var12.length;
for(int var14 = 0; var14 < var13; ++var14) {
Field field = var12[var14];
Advisor advisor = this.getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
List<Method> methods = new ArrayList();
ReflectionUtils.doWithMethods(aspectClass, (method) -> {
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
}, ReflectionUtils.USER_DECLARED_METHODS);
if (methods.size() > 1) {
methods.sort(METHOD_COMPARATOR);
}
return methods;
}
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) {
this.validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = this.getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
return expressionPointcut == null ? null : new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
} else {
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;
}
}
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
this.validate(candidateAspectClass);
AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
} else if (!this.isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]");
} else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
Object springAdvice;
switch(aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (this.logger.isDebugEnabled()) {
this.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())) {
((AbstractAspectJAdvice)springAdvice).setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing)aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
((AbstractAspectJAdvice)springAdvice).setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);
}
((AbstractAspectJAdvice)springAdvice).setAspectName(aspectName);
((AbstractAspectJAdvice)springAdvice).setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
((AbstractAspectJAdvice)springAdvice).setArgumentNamesFromStringArray(argNames);
}
((AbstractAspectJAdvice)springAdvice).calculateArgumentBindings();
return (Advice)springAdvice;
}
}
可以看出Spring会对不同注解的方法生成不同的增强器如AspectJAroundAdvice、AspectJAfterReturningAdvice等
以@Before注解为例
- 在拦截链中放置MethodBeforeAdviceInterceptor ,MethodBeforeAdviceInterceptor 完成了增强逻辑
- 在MethodBeforeAdviceInterceptor 放置AspectJMethodBeforeAdvice
- 在调用invoke方法的时候串联调用,// 调用AspectJMethodBeforeAdvice的前置增强方法然后才是 // 方法执行
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;
}
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);
}
protected Object invokeAdviceMethod(@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex) throws Throwable {
return this.invokeAdviceMethodWithGivenArgs(this.argBinding(this.getJoinPoint(), jpMatch, returnValue, ex));
}
protected transient Method aspectJAdviceMethod;
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
} catch (IllegalArgumentException var4) {
throw new AopInvocationException("Mismatch on arguments to advice method [" + this.aspectJAdviceMethod + "]; pointcut expression [" + this.pointcut.getPointcutExpression() + "]", var4);
} catch (InvocationTargetException var5) {
throw var5.getTargetException();
}
}
以@After注解为例
和前置不同,直接在拦截器链中使用了中间的AspectJAfterAdvice
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable {
public AspectJAfterAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
public Object invoke(MethodInvocation mi) throws Throwable {
Object var2;
try {
var2 = mi.proceed();
} finally {
this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);
}
return var2;
}
public boolean isBeforeAdvice() {
return false;
}
public boolean isAfterAdvice() {
return true;
}
}
// 2.1.2 findAdvisorsThatCanApply
之前找到所有的增强之后封装为XxxAdvice,然后就是遍历找出该bean能运用的放到List集合
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
List var4;
try {
var4 = AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
} finally {
ProxyCreationContext.setCurrentProxiedBeanName((String)null);
}
return var4;
}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
} else {
List<Advisor> eligibleAdvisors = new ArrayList();
Iterator var3 = candidateAdvisors.iterator();
while(var3.hasNext()) {
Advisor candidate = (Advisor)var3.next();
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
Iterator var7 = candidateAdvisors.iterator();
while(var7.hasNext()) {
Advisor candidate = (Advisor)var7.next();
if (!(candidate instanceof IntroductionAdvisor) && canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
}
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;
}
}
// 2.2 createProxy创建代理
如果可以运用的增强方法不为空,需要为该bean创建代理执行增强方法,
// 2.2.1 设置beanDefinition原来的属性
// 2.2.2 实例化proxyFactory ,内部封装了getProxy等方法,需要根据下面的配置进去的属性获取代理对象
// 2.2.3 获取当前bean的属性
// 2.2.4 设置属性,根据我们配置的proxy-target-class属性,选用JDK还是Cglib动态代理时需要用到保存在ProxyFactory中的该属性
// 2.2.5 加入能用的增强器,复杂
// 2.2.6 设置被代理类
// 2.2.7 定制代理
// 2.2.8 委托ProxyFactory获取代理对象,复杂
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (this.shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
this.evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
this.customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (this.advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(this.getProxyClassLoader());
}
// 2.2.5 buildAdvisors封装能用的增强器
因为Spring涉及了过多的拦截器、增强器、增强方法等方式对逻辑进行增强,所以非常有必要封装成为Advisor来进行代理的创建
简单来说:Advice 是通知,Advisor 是增强器。使用 spring aop 要定义切面,切面里面有 通知 和 切点。
在项目启动的过程中,项目中的所有切面会被 AnnotationAwareAspectJAutoProxyCreator 解析,它会找到切面中的每一个通知以及通知对应的切点,拿这二者构建一个新的对象,这个对象就是 Advisor。最后将所有解析得到的增强器注入到容器中。
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
Advisor[] commonInterceptors = this.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));
}
}
}
int i;
if (this.logger.isTraceEnabled()) {
int nrOfCommonInterceptors = commonInterceptors.length;
i = specificInterceptors != null ? specificInterceptors.length : 0;
this.logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors + " common interceptors and " + i + " specific interceptors");
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for(i = 0; i < allInterceptors.size(); ++i) {
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor)adviceObject;
} else if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
} else {
Advice advice = (Advice)adviceObject;
if (advice instanceof MethodInterceptor) {
return new DefaultPointcutAdvisor(advice);
} else {
Iterator var3 = this.adapters.iterator();
AdvisorAdapter adapter;
do {
if (!var3.hasNext()) {
throw new UnknownAdviceTypeException(advice);
}
adapter = (AdvisorAdapter)var3.next();
} while(!adapter.supportsAdvice(advice));
return new DefaultPointcutAdvisor(advice);
}
}
}
// 2.2.8 委托ProxyFactory获取代理对象
public Object getProxy(@Nullable ClassLoader classLoader) {
return this.createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
this.activate();
}
return this.getAopProxyFactory().createAopProxy(this);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
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.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
在分析JDK动态代理和Cglib动态代理之前,先看看如何使用
- 使用JDK动态代理:需要被代理类实现某个接口
- 创建处理器MyInvocationHandler实现InvocationHandler接口,重写invoke、getProxy()方法(也可以放到外面直接Proxy.newProxyInstance()获得代理对象),然后构造方法传入被代理对象
- 创建被代理对象实例,传入MyInvocationHandler实例
- 通过MyInvocationHandler.getProxy()获得代理对象proxy
- 测试 proxy.test()
- 使用Cglib动态代理:要求被代理类不能被final修饰
- 创建处理器MyMethodInterceptor实现MethodInterceptor,重写intercepter()方法
- 测试,创建Enhancer实例
- 调用setSuperClass()设置被代理类Class,
- 调用setCallback()传入MyMethodInterceptor实例,
- 调用create()方法创建代理对象,然后调用方法test()
// JdkDynamicAopProxy处理器分析
可以看到// final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable 它也实现 InvocationHandler
关键点就是invoke、getProxy方法
public Object getProxy() {
return this.getProxy(ClassUtils.getDefaultClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
invoke方法主要是创建了一个拦截器链,然后使用ReflectiveMethodInvocation封装,在他的proceed()方法实现拦截器的逐一调用
@Nullable
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;
Object retVal;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
Boolean var18 = this.equals(args[0]);
return var18;
}
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
Integer var17 = this.hashCode();
return var17;
}
if (method.getDeclaringClass() == DecoratingProxy.class) {
Class var16 = AopProxyUtils.ultimateTargetClass(this.advised);
return var16;
}
if (this.advised.opaque || !method.getDeclaringClass().isInterface() || !method.getDeclaringClass().isAssignableFrom(Advised.class)) {
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 {
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);
}
Object var12 = retVal;
return var12;
}
retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
return retVal;
}
@Nullable
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.invokeJoinpoint();
} else {
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass();
return dm.methodMatcher.matches(this.method, targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
} else {
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}
// Cglib2AopProxy处理器分析
首先需要导入依赖
<dependency>
<groupId>springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>1.2.5</version>
</dependency>
getProxy方法
public Object getProxy() {
return this.getProxy((ClassLoader)null);
}
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
Class targetClass = this.advised.getTargetSource().getTargetClass();
logger.debug("Creating CGLIB2 proxy" + (targetClass != null ? " for [" + targetClass.getName() + "]" : ""));
}
Enhancer enhancer = new Enhancer();
try {
Class rootClass = this.advised.getTargetSource().getTargetClass();
Class proxySuperClass = AopUtils.isCglibProxyClass(rootClass) ? rootClass.getSuperclass() : rootClass;
this.validateClassIfNecessary(proxySuperClass);
enhancer.setSuperclass(proxySuperClass);
enhancer.setCallbackFilter(new Cglib2AopProxy.ProxyCallbackFilter(this.advised));
enhancer.setStrategy(new UndeclaredThrowableStrategy(class$java$lang$reflect$UndeclaredThrowableException == null ? (class$java$lang$reflect$UndeclaredThrowableException = class$("java.lang.reflect.UndeclaredThrowableException")) : class$java$lang$reflect$UndeclaredThrowableException));
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
Callback[] callbacks = this.getCallbacks(rootClass);
enhancer.setCallbacks(callbacks);
if (Cglib2AopProxy.CglibUtils.canSkipConstructorInterception()) {
enhancer.setInterceptDuringConstruction(false);
}
Class[] types = new Class[callbacks.length];
for(int x = 0; x < types.length; ++x) {
types[x] = callbacks[x].getClass();
}
enhancer.setCallbackTypes(types);
Object proxy;
if (this.constructorArgs != null) {
proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);
} else {
proxy = enhancer.create();
}
return proxy;
} catch (CodeGenerationException var8) {
throw new AspectException("Couldn't generate CGLIB subclass of class '" + this.advised.getTargetSource().getTargetClass() + "': " + "Common causes of this problem include using a final class or a non-visible class", var8);
} catch (IllegalArgumentException var9) {
throw new AspectException("Couldn't generate CGLIB subclass of class '" + this.advised.getTargetSource().getTargetClass() + "': " + "Common causes of this problem include using a final class or a non-visible class", var9);
} catch (Exception var10) {
throw new AspectException("Unexpected AOP exception", var10);
}
}
intercepter方法
private class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private DynamicAdvisedInterceptor() {
}
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
MethodInvocation invocation = null;
Object oldProxy = null;
boolean setProxyContext = false;
Class targetClass = null;
Object target = null;
Object var12;
try {
Object retVal = null;
if (Cglib2AopProxy.this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = this.getTarget();
if (target != null) {
targetClass = target.getClass();
}
List chain = Cglib2AopProxy.this.advised.getAdvisorChainFactory().getInterceptorsAndDynamicInterceptionAdvice(Cglib2AopProxy.this.advised, proxy, method, targetClass);
if (chain.isEmpty()) {
retVal = methodProxy.invoke(target, args);
} else {
invocation = new Cglib2AopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy);
retVal = invocation.proceed();
}
retVal = Cglib2AopProxy.massageReturnTypeIfNecessary(proxy, target, retVal);
var12 = retVal;
} finally {
if (target != null) {
this.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
return var12;
}
public int hashCode() {
return Cglib2AopProxy.this.advised.hashCode();
}
protected Object getTarget() throws Exception {
return Cglib2AopProxy.this.advised.getTargetSource().getTarget();
}
protected void releaseTarget(Object target) throws Exception {
Cglib2AopProxy.this.advised.getTargetSource().releaseTarget(target);
}
}
三、AspectJ动态织入
AspectJ 的底层技术是 静态代理 ,主要是在虚拟机启动的时候通过改变目标对象字节码的方式来完成对目标对象的增强,它比动态代理有更高的效率,因为在动态代理调用过程中,还需要一个动态创建代理类并代理目标对象的步骤,而静态代理是在启动时完成了字节码增强,当系统调用目标类和正常的类无差别,所以效率上会相对高一些。
Aspect是实现AOP编程的一种具体实现
- 编译时织入,利用ajc编译器替代javac编译器,直接将源文件(java或者aspect文件)编译成class文件并将切面织入进代码。
- 编译后织入,利用ajc编译器向javac编译期编译后的class文件或jar文件织入切面代码。
- 加载时织入(LTW),不使用ajc编译器,利用aspectjweaver.jar工具,使用java agent代理在类加载期将切面织入进代码。
前两种织入方法都依赖于ajc的编译工具,LTW却通过java agent机制在内存中操作类文件,可以不需要ajc的支持做到 动态织入
不过,这里有一个挺有意思的问题,我们知道编译期一定会编译AnnoAspect类,那么这时候通过切面语法我们就可以找到他要处理的App类,这大概就是编译阶段织入的大概流程。
但是如果在类加载期处理的话,当类加载到App类的时候,我们并不知道这个类需要被AnnoAspect处理。。。因此为了实现LTW,我们肯定要有个配置文件,来告诉类加载器,某某某切面需要优先考虑,他们很可能会影响其他的类。为了实现LTW,我们需要在资源目录下配置META-INF/aop.xml文件,来告知类加载器我们当前注册的切面。
比如说Load-Time Weaving的方式 还 需要额外的jar包 spring-instrument.jar。 当然,无论是使用spring aop还是 aspectj都需要aspectjweaver.jar spring-aop.jar这两个jar包。
?
参考:https://blog.csdn.net/whatigame/article/details/103173308
使用步骤
- 在xml配置文件中加上
<aop:aspect-autoproxy> 、<context:load-time-weaver> 开启Load-Time Weaving开关 - 在class路径下新建META-INF文件夹,文件夹创建aop.xml文件,里面配置
<aspect>、 <weaver>、<aspects> 主要是告诉AspectJ哪些包进行织入,并使用哪些增强器 - 加入启动参数,也就是应用指定的jar包
- 测试
|