gpt4 book ai didi

Spring读源码系列之AOP--05---aop常用工具类学习

转载 作者:知者 更新时间:2024-03-13 01:46:59 26 4
gpt4 key购买 nike

引言

Spring AOP框架的代码结构组织得不可为不好,良好的面向对象的编程思想,其中很有一部分得益于它对代码的结构的把控。良好的封装、分层、隔离。而在其中起到重要作用的,便是本文要盘点的一些工具类。

Spring框架的工具类,其实它是分为内部工具类和外部工具类的。如果是外部工具类,那是可以给调用者使用的,如果是内部工具类,那它一般都是在Spring的流程内部使用。

环境搭建

public interface HelloService {
    Object hello();
}
public class HelloServiceImpl implements HelloService{
    @Override
    public Object hello() {
        System.out.println("HelloServiceImpl is invoked");
        return "hello world";
    }
}
public class AopUtilMain {
    public static void main(String[] args) {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(new HelloServiceImpl());
        proxyFactory.addAdvice((MethodBeforeAdvice)(method, args1, target)->{
            System.out.println("前置通知~~~");
        });

        HelloService helloService = (HelloService) proxyFactory.getProxy();
        helloService.hello();
        System.out.println(helloService.getClass().getName());
    }
}

测试:

AopUtils—aop常用方法抽离

该工具类是Spring非常重要的一个工具类。显然它是一个外部工具类,我们平时若想要对AOP做一些判断、处理,也是可议使用此工具类的。

public abstract class AopUtils {

	/**
     当前对象是否是代理类,可能被jdk或者cglib动态代理
	 */
	public static boolean isAopProxy(@Nullable Object object) {
		return (object instanceof SpringProxy && (Proxy.isProxyClass(object.getClass()) ||
				object.getClass().getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)));
	}

	/**
      是否是jdk动态代理   
	 */
	public static boolean isJdkDynamicProxy(@Nullable Object object) {
		return (object instanceof SpringProxy && Proxy.isProxyClass(object.getClass()));
	}

	/**
    是否是cglib动态代理
	 */
	public static boolean isCglibProxy(@Nullable Object object) {
		return (object instanceof SpringProxy &&
				object.getClass().getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR));
	}

	/**
     如果传入的对象是代理对象则返回目标对象的类型,否则返回传入对象的class类型
	 */
	public static Class<?> getTargetClass(Object candidate) {
		Assert.notNull(candidate, "Candidate object must not be null");
		Class<?> result = null;
		//TargetClassAware提供了暴露目标对象类型的api
		if (candidate instanceof TargetClassAware) {
			result = ((TargetClassAware) candidate).getTargetClass();
		}
		if (result == null) {
            //是否是被cglib代理的对象,如果是返回代理对象的父类类型即目标对象的class类型
            //否在返回当前对象本身的类型			
			result = (isCglibProxy(candidate) ? candidate.getClass().getSuperclass() : candidate.getClass());
		}
		return result;
	}

	/**
method在targetType类和其父接口上是否存在,存在就返回
这里targetType通常是代理类
	 */
	public static Method selectInvocableMethod(Method method, @Nullable Class<?> targetType) {
		if (targetType == null) {
			return method;
		}
		//MethodIntrospector.selectInvocableMethod是去寻找targetType类中是否存在method方法,如果不存在在去targetType
		//的父接口中寻找是否存在,存在即返回,否在抛出异常
		Method methodToUse = MethodIntrospector.selectInvocableMethod(method, targetType);
		//当前方法如果是私有的并且是非静态的并且是targetType是代理类
		if (Modifier.isPrivate(methodToUse.getModifiers()) && !Modifier.isStatic(methodToUse.getModifiers()) &&
				SpringProxy.class.isAssignableFrom(targetType)) {
			throw new IllegalStateException(String.format(
					"Need to invoke method '%s' found on proxy for target class '%s' but cannot " +
					"be delegated to target bean. Switch its visibility to package or protected.",
					method.getName(), method.getDeclaringClass().getSimpleName()));
		}
		//返回找到的这个方法
		return methodToUse;
	}
    
    //四个特殊方法的判断
	public static boolean isEqualsMethod(@Nullable Method method) {
		return ReflectionUtils.isEqualsMethod(method);
	}

	public static boolean isHashCodeMethod(@Nullable Method method) {
		return ReflectionUtils.isHashCodeMethod(method);
	}

	public static boolean isToStringMethod(@Nullable Method method) {
		return ReflectionUtils.isToStringMethod(method);
	}

	public static boolean isFinalizeMethod(@Nullable Method method) {
		return (method != null && method.getName().equals("finalize") &&
				method.getParameterCount() == 0);
	}

	/**
Given a method, which may come from an interface, and a target class used in the current AOP invocation, find the corresponding target method if there is one. E.g. the method may be IFoo.bar() and the target class may be DefaultFoo. In this case, the method may be DefaultFoo.bar(). This enables attributes on that method to be found.

NOTE: In contrast to ClassUtils.getMostSpecificMethod, this method resolves Java 5 bridge methods in order to retrieve attributes from the original method definition.
	 */
	public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass) {
		Class<?> specificTargetClass = (targetClass != null ? ClassUtils.getUserClass(targetClass) : null);
		Method resolvedMethod = ClassUtils.getMostSpecificMethod(method, specificTargetClass);
		// If we are dealing with method with generic parameters, find the original method.
		return BridgeMethodResolver.findBridgedMethod(resolvedMethod);
	}

	public static boolean canApply(Pointcut pc, Class<?> targetClass) {
		return canApply(pc, targetClass, false);
	}

	/**
给定的切入点可以完全应用于给定的类吗?

asIntroductions – whether or not the advisor chain for this bean includes any introductions
	 */
	public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");
		//先从类级别进行过滤
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}
       //再从方法级别进行过滤
		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}

		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		Set<Class<?>> classes = new LinkedHashSet<>();
		//目标对象如果不是jdk代理类
		if (!Proxy.isProxyClass(targetClass)) {
		//getUserClass会尝试去处理cglib代理的情况,返回代理类的父类类型即目标对象类型---cglib
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		//加入当前类实现的所有接口---jdk
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
        
        //遍历 
		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;
	}

	public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
	//IntroductionAdvisor只需要进行类级别过滤即可
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			//调用上面分析的重载canApply方法
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			//其他类型的advisor没有ponitcut,默认都可以应用
			return true;
		}
	}

	public static boolean canApply(Pointcut pc, Class<?> targetClass) {
		return canApply(pc, targetClass, false);
	}
	
	public static boolean canApply(Advisor advisor, Class<?> targetClass) {
		return canApply(advisor, targetClass, false);
	}
	
	/**
从传入的候选advisors集合中,寻找到能应用到当前calss上的增强器有哪些
	 */
	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new ArrayList<>();
		for (Advisor candidate : candidateAdvisors) {
		//如果是IntroductionAdvisor ,那么直接进行类级别过滤级别,调用canApply其中一个重载方法完成类级别的过滤
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
			//如果发现满足类匹配的条件,加入候选增强器集合
				eligibleAdvisors.add(candidate);
			}
		}
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
		//IntroductionAdvisor上面已经处理过了
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
			//判断ponitcutAdvisor和其他类型的Advisor能否应用
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

	/**
使用反射调用连接点上的方法	
反射调用target上的method方法,传入方法参数args
	 */
	@Nullable
	public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
			throws Throwable {

		// Use reflection to invoke the method.
		try {
		//确保私有方法也可以反射调用
			ReflectionUtils.makeAccessible(method);
			return method.invoke(target, args);
		}
		catch (InvocationTargetException ex) {
			// Invoked method threw a checked exception.
			// We must rethrow it. The client won't see the interceptor.
			throw ex.getTargetException();
		}
		catch (IllegalArgumentException ex) {
			throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
					method + "] on target [" + target + "]", ex);
		}
		catch (IllegalAccessException ex) {
			throw new AopInvocationException("Could not access method [" + method + "]", ex);
		}
	}

}

AopUtils使用演示

public static void main(String[] args) {
        HelloService helloService = getProxy(new HelloServiceImpl());
        //===============演示AopUtils==================

        // AopUtils.isAopProxy:是否是代理对象
        System.out.println(AopUtils.isAopProxy(helloService)); // true
        System.out.println(AopUtils.isJdkDynamicProxy(helloService)); // false
        System.out.println(AopUtils.isCglibProxy(helloService)); // true

        // 拿到目标对象
        System.out.println(AopUtils.getTargetClass(helloService)); //class com.fsx.service.HelloServiceImpl

        // selectInvocableMethod:方法@since 4.3  底层依赖于方法MethodIntrospector.selectInvocableMethod
        // 只是在他技术上做了一个判断: 必须是被代理的方法才行(targetType是SpringProxy的子类,且是private这种方法,且不是static的就不行)
        // Spring MVC的detectHandlerMethods对此方法有大量调用~~~~~
        Method method = ClassUtils.getMethod(HelloServiceImpl.class, "hello");
        System.out.println(AopUtils.selectInvocableMethod(method, HelloServiceImpl.class)); //public java.lang.Object com.fsx.service.HelloServiceImpl.hello()

        // 是否是equals方法
        // isToStringMethod、isHashCodeMethod、isFinalizeMethod  都是类似的
        System.out.println(AopUtils.isEqualsMethod(method)); //false

        // 它是对ClassUtils.getMostSpecificMethod,增加了对代理对象的特殊处理。。。
        System.out.println(AopUtils.getMostSpecificMethod(method,HelloService.class));
	}

AopConfigUtils—自动代理创建器的管理

从名字可以看出,这个是关于AOP配置的工具类。因为配置AOP的方式有多种(比如xml、注解等),此工具类就是针对不同配置,提供不同的工具方法的。

它的好处是不管什么配置,最终走底层逻辑都让归一了~~~~

类注释翻译:

该类是来管理自动代理创建器的注册

应该只注册一个自动代理创建者,但可以使用多个具体实现。

此类提供了一个简单的升级协议,允许调用者请求特定的自动代理创建者,并知道该创建者或其更强大的变体将被注册为后处理器。

public abstract class AopConfigUtils {

	/**
	 *  这是注册自动代理创建器,默认的BeanName(若想覆盖,需要使用这个BeanName)
	 */
	public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";

	/**
	 *  按照升级顺序 存储自动代理创建器(注意这里是升级的顺序 一个比一个强的)
	 */
	private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);

	static {
		// Set up the escalation list...
		//这里每个自动代理创建器都对应一个优先级,优先级就是该自动代理创建器再集合中的下标,下标越大,优先级越高
		APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
	}

    // 这两个:注册的是`InfrastructureAdvisorAutoProxyCreator`  
	// 调用处为:AutoProxyRegistrar#registerBeanDefinitions(它是一个ImportBeanDefinitionRegistrar实现类) 
	// 而AutoProxyRegistrar使用处为CachingConfigurationSelector,和`@EnableCaching`注解有关
	// 其次就是AopNamespaceUtils有点用,这个下面再分析
	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAutoProxyCreatorIfNecessary(registry, null);
	}
	
	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
       
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}

	// 下面这两个是注入:AspectJAwareAdvisorAutoProxyCreator
	// 目前没有地方默认调用~~~~和Aop的xml配置方案有关的
	@Nullable
	public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAspectJAutoProxyCreatorIfNecessary(registry, null);
	}

	@Nullable
	public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
	}


	// 这个就是最常用的,注入的是:AnnotationAwareAspectJAutoProxyCreator  注解驱动的自动代理创建器
	// `@EnableAspectJAutoProxy`注入进来的就是它了
	@Nullable
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
	}
	@Nullable
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}

	// 这两个方法,很显然,就是处理注解的两个属性值
	// proxyTargetClass:true表示强制使用CGLIB的动态代理
	// exposeProxy:true暴露当前代理对象到线程上绑定
	// 最终都会放到自动代理创建器得BeanDefinition 里面去~~~创建代理的时候会用到此属性值
	public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
		}
	}

	public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
		}
	}

	//========上面的注册自动代理创建器IfNecessary之类的方法,最终都是调用了这里========
	@Nullable
	private static BeanDefinition registerOrEscalateApcAsRequired(
			Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
       //如果容器中包含了AUTO_PROXY_CREATOR_BEAN_NAME对应的beanName,那么此时再进行注册操作就需要根据优先级来判断是否需要进行覆盖
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			//拿到容器中现存的自动代理创建器
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			//当然要注册进容器的bean和容器中现存的bean的类型不能一样,否则不进行操作
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
			//获取容器中已有的自动代理创建器的优先级
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
			//获取要注册进容器的自动代理创建器的优先级
				int requiredPriority = findPriorityForClass(cls);
				//只有在优先级更大的情况下,才会覆盖成功
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			return null;
		}
        //容器中还没有自动代理创建器,那么就直接把当前要注册进容器的自动代理创建器注册到容器中
        	// 绝大部分情况下都会走这里,new一个Bean定义信息出来,然后order属性值为HIGHEST_PRECEDENCE
		// role是:ROLE_INFRASTRUCTURE属于Spring框架自己使用的Bean
		// BeanName为:AUTO_PROXY_CREATOR_BEAN_NAME
		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		//注册beanDefinition
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}
   
    //优先级就是根据当前自动代理创建器在集合中的序号决定的
	private static int findPriorityForClass(Class<?> clazz) {
		return APC_PRIORITY_LIST.indexOf(clazz);
	}

	private static int findPriorityForClass(@Nullable String className) {
		for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) {
			Class<?> clazz = APC_PRIORITY_LIST.get(i);
			if (clazz.getName().equals(className)) {
				return i;
			}
		}
		throw new IllegalArgumentException(
				"Class name [" + className + "] is not a known auto-proxy creator class");
	}

}

由于AopConfigUtils 并没有公开可以向APC_PRIORITY_LIST 中添加元素的方法,因此我们只能注册他规定的三种自动代理创建器

备注:请尽量不要自定义自动代理创建器,也不要轻易使用低级别的创建器,若你对原理不是非常懂的话,慎重

AopNamespaceUtils—xml形式aop处理

这个从名字可以看出,是处理Spring AOP命名空间的工具类。比如

xmlns:aop="http://www.springframework.org/schema/aop

处理这种xml里面的

<aop:config />
<aop:advice />

等这种。当然还有对proxy-target-class和expose-proxy的处理。因为接下来的重点都不在xml里,因此此处略过(最终它调用都是AopConfigUtils#XXXIfNecessary的方法,去注册不同的自动代理创建器的)

AopProxyUtils—获取代理接口和代理类的相关操作

我理解成它是对org.springframework.aop.support.AopUtils的一个补充。

public abstract class AopProxyUtils {

	// JDK 17 Class.isSealed() method available?
	@Nullable
	private static final Method isSealedMethod = ClassUtils.getMethodIfAvailable(Class.class, "isSealed");

	/**
获取代理对象代理的目标对象
	 */
	@Nullable
	public static Object getSingletonTarget(Object candidate) {
	//如果传入的代理对象实现了Advised接口
		if (candidate instanceof Advised) {
		//拿到TargetSource
			TargetSource targetSource = ((Advised) candidate).getTargetSource();
			if (targetSource instanceof SingletonTargetSource) {
				//拿到目标对象
				return ((SingletonTargetSource) targetSource).getTarget();
			}
		}
		return null;
	}

	/**
返回代理对象代理的目标对象的class类型
	 */
	public static Class<?> ultimateTargetClass(Object candidate) {
		Assert.notNull(candidate, "Candidate object must not be null");
		Object current = candidate;
		Class<?> result = null;
		//如果代理对象实现了TargetClassAware接口,可以通过该接口直接获取到目标对象的类型
		while (current instanceof TargetClassAware) {
			result = ((TargetClassAware) current).getTargetClass();
			//拿到目标对象
			current = getSingletonTarget(current);
		}
		if (result == null) {
			//如果上面没能获取到结果
			//代理类是否是被cglib代理,如果是的话,返回代理类的父类类型,否则返回代理类自身类型
			result = (AopUtils.isCglibProxy(candidate) ? candidate.getClass().getSuperclass() : candidate.getClass());
		}
		return result;
	}

	/**
通过传入的aop配置,来决定最终代理对象需要实现的代理接口有哪些
	 */
	public static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised) {
		return completeProxiedInterfaces(advised, false);
	}

//decoratingProxy:代理对象是否要实现 DecoratingProxy接口
	static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
	//从代理配置中拿到当前代理对象设置的需要代理的接口
		Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
	//如果没有需要代理的接口
		if (specifiedInterfaces.length == 0) {
			// No user-specified interfaces: check whether target class is an interface.
			//拿到目标对象的类型
			Class<?> targetClass = advised.getTargetClass();
			if (targetClass != null) {
				//判断是否是接口,如果是,那么设置代理对象需要实现目标对象的接口
				if (targetClass.isInterface()) {
					advised.setInterfaces(targetClass);
				}
				//当前目标对象是否是jdk动态代理类型
				else if (Proxy.isProxyClass(targetClass)) {
					//如果是的话,拿到jdk动态代理类实现的接口,设置为需要实现的代理接口
					advised.setInterfaces(targetClass.getInterfaces());
				}
				specifiedInterfaces = advised.getProxiedInterfaces();
			}
		}
		//这边的+3,意味着下面可能需要实现额外的三个接口
		List<Class<?>> proxiedInterfaces = new ArrayList<>(specifiedInterfaces.length + 3);
		//jdk17的适配处理,这里先跳过
		for (Class<?> ifc : specifiedInterfaces) {
			// Only non-sealed interfaces are actually eligible for JDK proxying (on JDK 17)
			if (isSealedMethod == null || Boolean.FALSE.equals(ReflectionUtils.invokeMethod(isSealedMethod, ifc))) {
				proxiedInterfaces.add(ifc);
			}
		}
		//判断SpringProxy接口是否已经加入了代理类需要实现的接口,没加入则加入
		//即所有代理对象都会实现SpringProxy接口
		if (!advised.isInterfaceProxied(SpringProxy.class)) {
			proxiedInterfaces.add(SpringProxy.class);
		}
		//proxyConfig的opaque属性是否为true,该属性为true,则表示代理类不能强制转换为advised接口,默认为false,即代理类需要继承advised接口
		//还有一点需要保证,就是Advised未被加入需要代理的接口数组中
		if (!advised.isOpaque() && !advised.isInterfaceProxied(Advised.class)) {
			proxiedInterfaces.add(Advised.class);
		}
		//decoratingProxy属性来确保代理类是否需要实现DecoratingProxy接口,该接口会暴露api来获取到代理对象代理的目标对象的类型
		if (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)) {
			proxiedInterfaces.add(DecoratingProxy.class);
		}
		//返回最终需要实现的代理接口集合
		return ClassUtils.toClassArray(proxiedInterfaces);
	}

	/**
获取传入的代理对象实现的接口中,用户指定的代理接口,因为上面的方法我们已经看到了,可能需要额外实现三个接口
	 */
	public static Class<?>[] proxiedUserInterfaces(Object proxy) {
	//拿到代理类已经实现的所有接口
		Class<?>[] proxyInterfaces = proxy.getClass().getInterfaces();
		int nonUserIfcCount = 0;
		//判断下面三个接口实现了几个
		if (proxy instanceof SpringProxy) {
			nonUserIfcCount++;
		}
		if (proxy instanceof Advised) {
			nonUserIfcCount++;
		}
		if (proxy instanceof DecoratingProxy) {
			nonUserIfcCount++;
		}
		//行为额外新增加的三个接口,会放在数组尾部,因此从尾部嘎掉他们即可
		Class<?>[] userInterfaces = Arrays.copyOf(proxyInterfaces, proxyInterfaces.length - nonUserIfcCount);
		Assert.notEmpty(userInterfaces, "JDK proxy must implement one or more interfaces");
		return userInterfaces;
	}

	/**
	 * Check equality of the proxies behind the given AdvisedSupport objects.
	 * Not the same as equality of the AdvisedSupport objects:
	 * rather, equality of interfaces, advisors and target sources.
	 */
	public static boolean equalsInProxy(AdvisedSupport a, AdvisedSupport b) {
		return (a == b ||
				(equalsProxiedInterfaces(a, b) && equalsAdvisors(a, b) && a.getTargetSource().equals(b.getTargetSource())));
	}

	/**
	 * Check equality of the proxied interfaces behind the given AdvisedSupport objects.
	 */
	public static boolean equalsProxiedInterfaces(AdvisedSupport a, AdvisedSupport b) {
		return Arrays.equals(a.getProxiedInterfaces(), b.getProxiedInterfaces());
	}

	/**
	 * Check equality of the advisors behind the given AdvisedSupport objects.
	 */
	public static boolean equalsAdvisors(AdvisedSupport a, AdvisedSupport b) {
		return a.getAdvisorCount() == b.getAdvisorCount() && Arrays.equals(a.getAdvisors(), b.getAdvisors());
	}

	/**
	 * Adapt the given arguments to the target signature in the given method,
	 * if necessary: in particular, if a given vararg argument array does not
	 * match the array type of the declared vararg parameter in the method.
	 * 方法参数类型适配
	 */
	static Object[] adaptArgumentsIfNecessary(Method method, @Nullable Object[] arguments) {
		if (ObjectUtils.isEmpty(arguments)) {
			return new Object[0];
		}
		if (method.isVarArgs()) {
			if (method.getParameterCount() == arguments.length) {
				Class<?>[] paramTypes = method.getParameterTypes();
				int varargIndex = paramTypes.length - 1;
				Class<?> varargType = paramTypes[varargIndex];
				if (varargType.isArray()) {
					Object varargArray = arguments[varargIndex];
					if (varargArray instanceof Object[] && !varargType.isInstance(varargArray)) {
						Object[] newArguments = new Object[arguments.length];
						System.arraycopy(arguments, 0, newArguments, 0, varargIndex);
						Class<?> targetElementType = varargType.getComponentType();
						int varargLength = Array.getLength(varargArray);
						Object newVarargArray = Array.newInstance(targetElementType, varargLength);
						System.arraycopy(varargArray, 0, newVarargArray, 0, varargLength);
						newArguments[varargIndex] = newVarargArray;
						return newArguments;
					}
				}
			}
		}
		return arguments;
	}

}

JDK代理和CGLIB代理的获取代理对象方法都用使用到了该类中的方法:

// JDK代理的获取代理对象~~~
	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
		}
		// 这里就是获取到所有需要被代理的接口
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

AopProxyUtils中的方法不多,但是其中的ultimateTargetClass和completeProxiedInterfaces方法确是Spring AOP中比较重要的方法,也给

AopContext—aop上下文

包含用于获取有关当前 AOP 调用信息的静态方法的类。

如果 AOP 框架配置为公开当前代理(不是默认代理),则 currentProxy() 方法可用。它返回正在使用的 AOP 代理。目标对象或advice 可以使用它来进行advice 调用,就像在 EJB 中使用 getEJBObject() 一样。他们还可以使用它来查找advice configuration.。

Spring 的 AOP 框架默认不公开代理,因为这样做会降低性能。

此类中的功能可能由需要在调用时访问资源的目标对象使用。但是,如果有合理的替代方案,则不应使用此方法,因为它使应用程序代码依赖于 AOP 下的使用,尤其是 Spring AOP 框架。

public final class AopContext {

	/**
与此线程关联的 AOP 代理的 ThreadLocal 持有者。
除非控制代理配置上的“exposeProxy”属性设置为“true”,否则将包含 null。
	 */
	private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<>("Current AOP proxy");

	private AopContext() {
	}

	/**
尝试返回当前的 AOP 代理。仅当调用方法已通过 AOP 调用,
并且 AOP 框架已设置为公开代理时,此方法才可用。否则,此方法将抛出 IllegalStateException。
	 */
	public static Object currentProxy() throws IllegalStateException {
		Object proxy = currentProxy.get();
		if (proxy == null) {
			throw new IllegalStateException(
					"Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available, and " +
							"ensure that AopContext.currentProxy() is invoked in the same thread as the AOP invocation context.");
		}
		return proxy;
	}

	/**
通过 currentProxy() 方法使给定的代理可用。

请注意,调用者应注意适当地保留旧值。
	 */
	@Nullable
	static Object setCurrentProxy(@Nullable Object proxy) {
		Object old = currentProxy.get();
		if (proxy != null) {
			currentProxy.set(proxy);
		}
		else {
			currentProxy.remove();
		}
		return old;
	}

}

备注:这个工具类主要是和属性exposeProxy相关,让我们能够快捷的获取到AOP代理对象,而不是this对象。这个在事务不生效原因大解读的博文了得到了应用

AutoProxyUtils—是否应该被代理,获得目标对象类型和是否暴露目标对象

为自动代理组件准备的工具类。主要用于框架内部使用(AbstractAutoProxyCreator)

public abstract class AutoProxyUtils {

	// preserve:保护的  保留的
	// determine:查明  测定
	public static final String PRESERVE_TARGET_CLASS_ATTRIBUTE =
			Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "preserveTargetClass");

	public static final String ORIGINAL_TARGET_CLASS_ATTRIBUTE =
			Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "originalTargetClass");

	// 判断该beanName是否应该被代理
	// `AbstractAutoProxyCreator`里就有判断是否能够被代理。  如果能够被代理,那就采用CGLIB的代理方式了
	// 往里setAttr,目前只有`ConfigurationClassPostProcessor`对config配置类进行增强的时候
	public static boolean shouldProxyTargetClass(
			ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {

		if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
			BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
			return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
		}
		return false;
	}

	// 看看这个Bean定义的TargetClass
	// 如果Bean定义信息里面有ORIGINAL_TARGET_CLASS_ATTRIBUTE这个字段,那就不用getType()了
	// 以及ScopedProxyUtils创建和Scope有关的代理类的时候,其余地方都不会设置此属性
	@Nullable
	public static Class<?> determineTargetClass(
			ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {

		if (beanName == null) {
			return null;
		}
		if (beanFactory.containsBeanDefinition(beanName)) {
			BeanDefinition bd = beanFactory.getMergedBeanDefinition(beanName);
			Class<?> targetClass = (Class<?>) bd.getAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE);
			if (targetClass != null) {
				return targetClass;
			}
		}
		return beanFactory.getType(beanName);
	}

	//Expose the given target class for the specified bean, if possible
	// 就是在它的Bean定义信息里面,设置一个ORIGINAL_TARGET_CLASS_ATTRIBUTE属性,然后吧targetClass类型放进去
	// 也是子啊`AbstractAutoProxyCreator`创建代理的时候会这只进去的
	static void exposeTargetClass(
			ConfigurableListableBeanFactory beanFactory, @Nullable String beanName, Class<?> targetClass) {

		if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
			beanFactory.getMergedBeanDefinition(beanName).setAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE, targetClass);
		}
	}

	/**
根据 AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX 确定给定的 bean 名称是否指示“原始实例”,跳过任何代理尝试。
	 */
	static boolean isOriginalInstance(String beanName, Class<?> beanClass) {
	//beanName如果以.ORIGINAL结尾,则不进行代理操作
		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));
	}

}

AspectJAopUtils—前置和后置增强判断

相比于AopUtils,AspectJAopUtils是专门针对于AspectJ advisors的工具类。(当然AspectJ也是当下的主流方式)

public abstract class AspectJAopUtils {
// Advisor 是否是前置通知类型~~~~(Advisor都持有一个advice嘛)
	public static boolean isBeforeAdvice(Advisor anAdvisor) {
		AspectJPrecedenceInformation precedenceInfo = getAspectJPrecedenceInformationFor(anAdvisor);
		if (precedenceInfo != null) {
			return precedenceInfo.isBeforeAdvice();
		}
		return (anAdvisor.getAdvice() instanceof BeforeAdvice);
	}

// Advisor 是否是后置通知类型~~~~(Advisor都持有一个advice嘛)
	public static boolean isAfterAdvice(Advisor anAdvisor) {
		AspectJPrecedenceInformation precedenceInfo = getAspectJPrecedenceInformationFor(anAdvisor);
		if (precedenceInfo != null) {
			return precedenceInfo.isAfterAdvice();
		}
		return (anAdvisor.getAdvice() instanceof AfterAdvice);
	}

//拿到AspectJ的优先信息:AspectJPrecedenceInformation 
	@Nullable
	public static AspectJPrecedenceInformation getAspectJPrecedenceInformationFor(Advisor anAdvisor) {
		if (anAdvisor instanceof AspectJPrecedenceInformation) {
			return (AspectJPrecedenceInformation) anAdvisor;
		}
		Advice advice = anAdvisor.getAdvice();
		if (advice instanceof AspectJPrecedenceInformation) {
			return (AspectJPrecedenceInformation) advice;
		}
		return null;
	}

}

AspectJProxyUtils----将ExposeInvocationInterceptor放入增强链头部

同样的,它相对于AopProxyUtils,它只是专门处理AspectJ代理对象的工具类。

public abstract class AspectJProxyUtils {

	// 只提供这么一个公共方法,但是这个方法都还是非常重要的。 Capable:有能力的
	// 它在自动代理创建器`AspectJAwareAdvisorAutoProxyCreator#extendAdvisors`方法中有调用(重要~~~)
	// 在AspectJProxyFactory#addAdvisorsFromAspectInstanceFactory方法中也有调用
	// 它的作用:只要发现有AspectJ的Advisor存在,并且advisors还不包含有ExposeInvocationInterceptor.ADVISOR  那就在第一个位置上调添加一个ExposeInvocationInterceptor.ADVISOR
	public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
		// Don't add advisors to an empty list; may indicate that proxying is just not required
		if (!advisors.isEmpty()) {
			boolean foundAspectJAdvice = false;
			for (Advisor advisor : advisors) {
				// Be careful not to get the Advice without a guard, as this might eagerly
				// instantiate a non-singleton AspectJ aspect...
				if (isAspectJAdvice(advisor)) {
					foundAspectJAdvice = true;
					break;
				}
			}
			//只要发现当前增强器链存在AspectJAdvice,那么便尝试往advisors的中头部放入一个ExposeInvocationInterceptor
			//该拦截器的作用是将当前MethodInvocation调用链放到ThreadLocal中
			if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
				advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
				return true;
			}
		}
		return false;
	}

// 判断,该Advisor是否是AspectJ的的增强器
//这个方法也说明了AspectJExpressionPointcut,AbstractAspectJAdvice 和InstantiationModelAwarePointcutAdvisor 都是和AspectJ相关的类包括他们下面的子类
	private static boolean isAspectJAdvice(Advisor advisor) {
		return (advisor instanceof InstantiationModelAwarePointcutAdvisor ||
				advisor.getAdvice() instanceof AbstractAspectJAdvice ||
				(advisor instanceof PointcutAdvisor &&
						((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
	}
...
}

ExposeInvocationInterceptor—将当前MethodInvocation放入ThreadLocal中

某些通知内部会用到调用链对象,所以我们在执行的时候需要将调用链放在让所有通知都能获取到的一个地方,哪里呢?

  • 当前线程内,因为当前调用链肯定是在同一个线程内执行的,因此每个切面都可以获取到当前线程内的调用链

放入当前线程的工作是由spring自动添加的一个外层环绕通知完成的,这里也解释了为什么spring会默认添加的一个最外层的通知

public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {

	/** 单例体现. */
	public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();

	/**
	 * Singleton advisor for this class. Use in preference to INSTANCE when using
	 * Spring AOP, as it prevents the need to create a new Advisor to wrap the instance.
	 */
	public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
		@Override
		public String toString() {
			return ExposeInvocationInterceptor.class.getName() +".ADVISOR";
		}
	};

//存放当前MethodInvocation
	private static final ThreadLocal<MethodInvocation> invocation =
			new NamedThreadLocal<>("Current AOP method invocation");

//返回当前正在调用的MethodInvocation
	public static MethodInvocation currentInvocation() throws IllegalStateException {
		MethodInvocation mi = invocation.get();
		if (mi == null) {
			throw new IllegalStateException(
					"No MethodInvocation found: Check that an AOP invocation is in progress and that the " +
					"ExposeInvocationInterceptor is upfront in the interceptor chain. Specifically, note that " +
					"advices with order HIGHEST_PRECEDENCE will execute before ExposeInvocationInterceptor! " +
					"In addition, ExposeInvocationInterceptor and ExposeInvocationInterceptor.currentInvocation() " +
					"must be invoked from the same thread.");
		}
		return mi;
	}

	/**
	 * Ensures that only the canonical instance can be created.
	 */
	private ExposeInvocationInterceptor() {
	}

//
	@Override
	@Nullable
	public Object invoke(MethodInvocation mi) throws Throwable {
		MethodInvocation oldInvocation = invocation.get();
		//当前线程的调用链更新
		invocation.set(mi);
		try {
		//调用链执行---递归调用
			return mi.proceed();
		}
		finally {
		//最后还是会将恢复为最开始的MethodInvocation 
			invocation.set(oldInvocation);
		}
	}

	@Override
	public int getOrder() {
		return PriorityOrdered.HIGHEST_PRECEDENCE + 1;
	}

	/**
	 * Required to support serialization. Replaces with canonical instance
	 * on deserialization, protecting Singleton pattern.
	 * <p>Alternative to overriding the {@code equals} method.
	 */
	private Object readResolve() {
		return INSTANCE;
	}

}

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com