aop源码浅析

说明:主要分成四部分,

  1. demo
  2. 后置处理器放入与调用时机(ioc中流程)
  3. 解析切面
  4. 怎么进行代理
  5. 怎么对增强进行排序

1 demo

1.1 pom.xml

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.9</version>
</dependency>

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.1</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.3.9</version>
</dependency>

1.2 配置类

package spring.kewen.ding.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan(basePackages = "spring.kewen.ding.bean")
@EnableAspectJAutoProxy
public class DingConfig {
}

1.3 切面

package spring.kewen.ding.bean.aop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class DingAspect {

    @Pointcut("execution(* spring.kewen.ding.bean.aop.*.*(..))")
    public void pointCut(){};

    @Before("pointCut()")
    public void before(){
        System.out.println("前置增强");
    }
    
    @After("pointCut()")
    public void after(){
        System.out.println("after");
    }
}

1.4 bean

package spring.kewen.ding.bean.aop;

import org.springframework.stereotype.Service;
@Service
public class UserService {
    public void print() {
        System.out.println("userService方法");
    }
}

1.5 启动类测试类

package spring.kewen.ding;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import spring.kewen.ding.bean.aop.UserService;
import spring.kewen.ding.config.DingConfig;

public class Application {
    public static void main(String[] args)  {
        AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(DingConfig.class);
        acac.getBean(UserService.class).print();
        acac.close();
    }
}

2 后置处理器放入与调用时机(ioc中流程)

2.1 第一阶段 将 AnnotationAwareAspectJAutoProxyCreator 转换成beandefinition,注册到容器

@EnableAspectJAutoProxy 注解开始,
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);

2.2 第二阶段将将beandefinition注册到单例池(ioc)

// ioc中这一步
registerBeanPostProcessors(beanFactory);

2.3 什么时候进行代理

// 初始化后,执行 BeanPostProcessor#postProcessAfterInitialization

3 解析切面

说明:解析时机为创建我们自定义的第一个对象的时候,调用的 AbstractAutoProxyCreator#postProcessBeforeInstantiation 方法(InstantiationAwareBeanPostProcessor的实现类)
// 调用链路

/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractBeanFactory#createBean

/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation

/*
AbstractAutoProxyCreator (这里以及以上都是创建对象前调用的后置处理器,如果这里有返回对象,则后面创建对象的流程都不会走,直接返回这里创建的对象)
*/
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

/*
AspectJAwareAdvisorAutoProxyCreator,从这个方法后,就是解析@Aspect注解以及@Before等,后面多些的几个方法栈,主要是没有什么功能
*/
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#shouldSkip

/*
AnnotationAwareAspectJAutoProxyCreator
*/
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findCandidateAdvisors

/*
BeanFactoryAspectJAdvisorsBuilder
*/
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors

/*
BeanFactoryAspectJAdvisorsBuilder
*/
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors

重点在于这一行:List classAdvisors = this.advisorFactory.getAdvisors(factory);
流程大致是:

  1. 找到@Aspect修饰的class,
  2. 然后循环字段和方法
  3. 解析pointcut
  4. 组装成InstantiationModelAwarePointcutAdvisorImpl
  5. 缓存起来

4 怎么进行代理

4.1 确定代理方式(jdk和cglib,简单来说,就是如果是面向接口编程就是jdk,否则就是cglib)

// 调用链路

/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractBeanFactory#createBean

/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

/*
AbstractAutowireCapableBeanFactory
*/
initializeBean:1790, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)

/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

/*
AbstractAutoProxyCreator
*/
org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization

/*
AbstractAutoProxyCreator
*/
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

/*
AbstractAutoProxyCreator
*/
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy

/*
ProxyFactory
proxyFactory.getProxy(classLoader)
*/
org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)

/*
ProxyCreatorSupport
*/
org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy

/*
DefaultAopProxyFactory
*/
org.springframework.aop.framework.AopProxyFactory#createAopProxy

// 重要代码

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	if (!NativeDetector.inNativeImage() &&
			(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
		Class<?> targetClass = config.getTargetClass();
		if (targetClass == null) {
			throw new AopConfigException("TargetSource cannot determine target class: " +
					"Either an interface or a target is required for proxy creation.");
		}
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}

// 每个判断条件的说明

  1. NativeDetector.inNativeImage()
    判断环境(System.Property)中这个org.graalvm.nativeimage.imagecode是否有值。此环境是否存在于本机映像中)
  2. config.isOptimize()
    表示是否开启了优化策略,这个默认为false
  3. config.isProxyTargetClass()
    如果这个属性为true的话,就代表是需要基于类进行代理的,说白了就是使用cglib代理的意思,而如果为false的话,那么就代表基于接口代理,也就是使用jdk代理。
  4. hasNoUserSuppliedProxyInterfaces(config)
    简单来说,要不就是目标类没有实现接口 ,要不就是目标类实现了接口且接口类型是SpringProxy,这两种情况只要满足一种就会返回true
-jdkcglib
NativeDetector.inNativeImage()falsefalse
config.isOptimize()falsefalse
config.isProxyTargetClass()falsetrue
hasNoUserSuppliedProxyInterfaces(config)falsetrue

另:cglib的时候,targetClass.isInterface()直接就是false,排除jdk动态代理

4.2 cglib动态代理生成

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
	}

	try {
		Class<?> rootClass = this.advised.getTargetClass();
		Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

		Class<?> proxySuperClass = rootClass;
		if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
			proxySuperClass = rootClass.getSuperclass();
			Class<?>[] additionalInterfaces = rootClass.getInterfaces();
			for (Class<?> additionalInterface : additionalInterfaces) {
				this.advised.addInterface(additionalInterface);
			}
		}

		// Validate the class, writing log messages as necessary.
		validateClassIfNecessary(proxySuperClass, classLoader);

		// Configure CGLIB Enhancer...
		Enhancer enhancer = createEnhancer();
		if (classLoader != null) {
			enhancer.setClassLoader(classLoader);
			if (classLoader instanceof SmartClassLoader &&
					((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
				enhancer.setUseCache(false);
			}
		}
		enhancer.setSuperclass(proxySuperClass);
		enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
		enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

		Callback[] callbacks = getCallbacks(rootClass);
		Class<?>[] types = new Class<?>[callbacks.length];
		for (int x = 0; x < types.length; x++) {
			types[x] = callbacks[x].getClass();
		}
		// fixedInterceptorMap only populated at this point, after getCallbacks call above
		enhancer.setCallbackFilter(new ProxyCallbackFilter(
				this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
		enhancer.setCallbackTypes(types);

		// Generate the proxy class and create a proxy instance.
		return createProxyClassAndInstance(enhancer, callbacks);
	}
	catch (CodeGenerationException | IllegalArgumentException ex) {
		throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
				": Common causes of this problem include using a final class or a non-visible class",
				ex);
	}
	catch (Throwable ex) {
		// TargetSource.getTarget() failed
		throw new AopConfigException("Unexpected AOP exception", ex);
	}
}

4.3 jdk动态代理生成

重要的类:org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
	}
	return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}

invok方法

@Override
@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;

	try {
		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
			// The target does not implement the equals(Object) method itself.
			return equals(args[0]);
		}
		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			// The target does not implement the hashCode() method itself.
			return hashCode();
		}
		else if (method.getDeclaringClass() == DecoratingProxy.class) {
			// There is only getDecoratedClass() declared -> dispatch to proxy config.
			return AopProxyUtils.ultimateTargetClass(this.advised);
		}
		else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
				method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			// Service invocations on ProxyConfig with the proxy config...
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}

		Object retVal;

		if (this.advised.exposeProxy) {
			// Make invocation available if necessary.
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}

		// Get as late as possible to minimize the time we "own" the target,
		// in case it comes from a pool.
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);

		// Get the interception chain for this method.
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		// Check whether we have any advice. If we don't, we can fallback on direct
		// reflective invocation of the target, and avoid creating a MethodInvocation.
		if (chain.isEmpty()) {
			// We can skip creating a MethodInvocation: just invoke the target directly
			// Note that the final invoker must be an InvokerInterceptor so we know it does
			// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
			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);
			// Proceed to the joinpoint through the interceptor chain.
			retVal = invocation.proceed();
		}

		// Massage return value if necessary.
		Class<?> returnType = method.getReturnType();
		if (retVal != null && retVal == target &&
				returnType != Object.class && returnType.isInstance(proxy) &&
				!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
			// Special case: it returned "this" and the return type of the method
			// is type-compatible. Note that we can't help if the target sets
			// a reference to itself in another returned object.
			retVal = proxy;
		}
		else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
			throw new AopInvocationException(
					"Null return value from advice does not match primitive return type for: " + method);
		}
		return retVal;
	}
	finally {
		if (target != null && !targetSource.isStatic()) {
			// Must have come from TargetSource.
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			// Restore old proxy.
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

5 怎么对增强进行排序

5.1 排序的规则

  • 首先定制规则的地方
    位置就在注册 AnnotationAwareAspectJAutoProxyCreator(aop后置处理器,属于BeanPostProcessor的实现类)的时候,在BeanFactoryAware#setBeanFactory 过程中会创建InstanceComparator对象,这这对象就是用来实现Compare的重要功能
  • 调用链路
/*
AbstractAutowireCapableBeanFactory
create AnnotationAwareAspectJAutoProxyCreator
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

/*
AbstractAutowireCapableBeanFactory
*/
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods

/*
AbstractAdvisorAutoProxyCreator
*/

org.springframework.beans.factory.BeanFactoryAware#setBeanFactory

/*
AnnotationAwareAspectJAutoProxyCreator
*/
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#initBeanFactory

/*
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory)
ReflectiveAspectJAdvisorFactory 静态代码块
静态代码块内容
Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
    new InstanceComparator<>(
            Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
    (Converter<Method, Annotation>) method -> {
        AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
        return (ann != null ? ann.getAnnotation() : null);
    });
*/
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory

/*
构造方法
InstanceComparator
*/
org.springframework.util.comparator.InstanceComparator#InstanceComparator
  • 重要代码
    // 构造方法
public InstanceComparator(Class<?>... instanceOrder) {
    Assert.notNull(instanceOrder, "'instanceOrder' array must not be null");
    this.instanceOrder = instanceOrder;
}
/*
说明:
instanceOrder 就是 org.aspectj.lang.annotation.Around 等class对象数组,顺序是:
 0 = {Class@1706} "interface org.aspectj.lang.annotation.Around"
 1 = {Class@1322} "interface org.aspectj.lang.annotation.Before"
 2 = {Class@1321} "interface org.aspectj.lang.annotation.After"
 3 = {Class@1707} "interface org.aspectj.lang.annotation.AfterReturning"
 4 = {Class@1708} "interface org.aspectj.lang.annotation.AfterThrowing"
*/

// org.springframework.util.comparator.InstanceComparator#getOrder

 private int getOrder(@Nullable T object) {
    if (object != null) {
        for (int i = 0; i < this.instanceOrder.length; i++) {
            if (this.instanceOrder[i].isInstance(object)) {
                return i;
            }
        }
    }
    return this.instanceOrder.length;
}
/*
由此可见,排序规则就是 
1).首先 创建 InstanceComparator 并初始化一个class数组,数组中元素的顺序是:Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
2).排序需要能比较的字段,或者规则,这个就是 某种增强在这个数组中下标的位置,如果是一个不存在的增强,直接返回数组长度
*/

5.2 排序的位置

排序的位置就在解析Aspect注解和@Before等注解的时候。
我们上面已经说明,解析注解一个重要点就是 List classAdvisors = this.advisorFactory.getAdvisors(factory);。
在这个方法中会拿到到所有家了增强注解的方法,这其中就进行了排序(List是有序的)

重点代码(debug方式进入的,不重要的进行跳过了):

  1. getAdvisors方法中有一个实现
for (Method method : getAdvisorMethods(aspectClass)) {
	Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
	if (advisor != null) {
		advisors.add(advisor);
	}
}
  1. getAdvisorMethods(aspectClass))
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
	List<Method> methods = new ArrayList<>();
	ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);
	if (methods.size() > 1) {
		methods.sort(adviceMethodComparator);
	}
	return methods;
}
  1. methods.sort(adviceMethodComparator);
@Override
public int compare(T o1, T o2) {
	int i1 = getOrder(o1);// 看到getOrder就差不多了
	int i2 = getOrder(o2);
	return (Integer.compare(i1, i2));
}

// 执行代理方法的时候,怎么执行,待续(责任链模式)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值