Spring专题--AOP--ProxyFactory

https://www.iteye.com/blog/elim-2397388

ProxyFactory 源码分析 https://www.iteye.com/blog/wangxinchun-2079024

https://blog.csdn.net/m0_38043362/article/details/80388698

https://www.iteye.com/blog/wangxinchun-2079024

Spring Aop是基于代理的,ProxyFactory是Spring Aop内部用来创建Proxy对象的一个工厂类。spring 提供的编程式aop实现,即通过 ProxyFactory类完成的。使用ProxyFactory时,我们需要为它指定我们需要代理的目标对象、代理时需要使用的Advisor或Advice。

指定Advisor

使用Aop时我们是需要对拦截的方法做一些处理的,对于Spring Aop来讲,需要对哪些方法调用做什么样的处理是通过Advisor来定义的,通常是一个PointcutAdvisor。PointcutAdvisor接口中包含主要有两个接口方法,一个用来获取Pointcut,一个用来获取Advice对象,它俩的组合就构成了需要在哪个Pointcut应用哪个Advice。所以有需要的时候我们也可以实现自己的Advisor实现。一个代理对象可以同时绑定多个Advisor对象,ProxyFactory的addAdvisor()方法可多次被调用。

指定Advice

依据我们对Spring Aop的了解,Spring的Aop代理对象绑定的就一定是一个Advisor,而且通常是一个PointcutAdvisor,通过它我们可以知道我们的Advice究竟是要应用到哪个Pointcut(哪个方法调用),当我们通过ProxyFactory在创建代理对象时绑定的是一个Advice对象时,实际上ProxyFactory内部还是为我们转换为了一个Advisor对象的,只是该Advisor对象对应的Pointcut是一个匹配所有方法调用的Pointcut实例。

源码解析

ProxyFactory:最常用的代理工厂应用,包含一些静态工厂方法,以及代理对象生成的方法。

ProxyCreatorSupport:代理工厂的基类,主要负责代理对象的生成。

数据结构:
ProxyConfig: 代理的基础配置属性
AdvisedSupport:提供基础的Advice的包装,Advisor 列表的维护,TargetSource 对象的维护,以及Interceptor 数据结构的解析和封装。

分析ProxyFactory 可以从两条线来分析:
1、代理对象的创建
2、method的调用以及拦截器(Advice)的织入。

代理对象的创建

public class ProxyFactory extends ProxyCreatorSupport {  
//指定待实现接口和拦截器  
   public ProxyFactory(Class proxyInterface, Interceptor interceptor) {  
        //Java程序在执行子类的构造方法之前,如果没有用 super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。 
        addInterface(proxyInterface); //JDK代理需要接口  
        addAdvice(interceptor);//添加增强逻辑  
    }  
}  
  
//通过指定一个目标对象,构造ProxyFactory,可以继续通过addAdvice(interceptor);添加拦截器  
public ProxyFactory(Object target) {  
        Assert.notNull(target, "Target object must not be null");  
        setInterfaces(ClassUtils.getAllInterfaces(target));  
        setTarget(target);  
    }  
  
//生成代理对象,createAopProxy 在ProxyCreatorSupport 中实现  
public Object getProxy() {  
        return createAopProxy().getProxy();  
    }  
  
}  
/** 代理工厂的基类,提供了对 AopProxyFactory 的包装*/  
public class ProxyCreatorSupport extends AdvisedSupport {  
  //代理工厂,默认实现 DefaultAopProxyFactory 提供了 JdkDynamicAopProxy 和 Cglib2AopProxy 的生成  
    private AopProxyFactory aopProxyFactory;   
  //aop配置的监听器  
    private List<AdvisedSupportListener> listeners = new LinkedList<AdvisedSupportListener>();  
  
    /** Set to true when the first AOP proxy has been created */  
    private boolean active = false;  
  
    /** 
     * 默认实现,指定DefaultAopProxyFactory 为默认aop代理生成工厂 
     */  
    public ProxyCreatorSupport() {  
        this.aopProxyFactory = new DefaultAopProxyFactory();  
    }  
  
    /** 
     * 同上自定义一个AopProxyFactory,来实现aop代理对象的生成 
     */  
    public ProxyCreatorSupport(AopProxyFactory aopProxyFactory) {  
        Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");  
        this.aopProxyFactory = aopProxyFactory;  
    }  
    /** 
     *留给子类调用的代理生成,此次是aop代理生成的入口 
     */  
    protected final synchronized AopProxy createAopProxy() {  
        if (!this.active) { //第一次激活的时候,调用相关的监听器  
            activate();  
        }
        //在ProxyFactory的构造方法中默认调用了该类的无参构造方法,生成了DefaultAopProxyFactory,所以此处调用的是DefaultAopProxyFactory的createAopProxy方法  
        return getAopProxyFactory().createAopProxy(this); //通过aop代理工厂 生成AopProxy  
    }  
  
}  
/** 默认的代理工厂实现 
当 optimize =true或proxyTargetClass=ture 或 no proxy interfaces 指定,使用CGLIB 来生成代理,否则jdk代理 
*/  
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {  
  
    /** 检查CGLIB2 相关类是否存在 */  
    private static final boolean cglibAvailable =  
            ClassUtils.isPresent("net.sf.cglib.proxy.Enhancer", DefaultAopProxyFactory.class.getClassLoader());  
  
  
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {  
        //optimize =true或proxyTargetClass=ture 或 no proxy interfaces 指定,使用CGLIB 来生成代理  
        //optimize 做优化,早期jdk的代理的生成相当慢,不过现在基本差异不大  
        if (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()) { //虽然符合以上要求,但是如果代理对象是接口,那么继续使用jdk  
                return new JdkDynamicAopProxy(config);  
            }  
            if (!cglibAvailable) {  
                throw new AopConfigException(  
                        "Cannot proxy target class because CGLIB2 is not available. " +  
                        "Add CGLIB to the class path or specify proxy interfaces.");  
            }  
            return CglibProxyFactory.createCglibProxy(config); // Cglib2 代理  
        }  
        else {  
            return new JdkDynamicAopProxy(config); //jdk 代理  
        }  
    }  
  
    /** 
     * 判断是否有接口 
     */  
    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {  
        Class[] interfaces = config.getProxiedInterfaces();  
        return (interfaces.length == 0 || (interfaces.length == 1 && SpringProxy.class.equals(interfaces[0])));  
    }  
  
    /** 
     * 创建Cglib2AopProxy 
     */  
    private static class CglibProxyFactory {  
        public static AopProxy createCglibProxy(AdvisedSupport advisedSupport) {  
            return new Cglib2AopProxy(advisedSupport);  
        }  
    }  
}  
/** 
 * 基于JDK动态代理 的Aop代理实现 
   通过JDK代理的方法调用 只对接口中的方法做拦截 
   即使真实对象不是线程安全的,通过JdkDynamicAopProxy 产生的对象依然是线程安全的。 
 */  
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {  
  
    private static final long serialVersionUID = 5531744639992436476L;  
  
    /** We use a static Log to avoid serialization issues */  
    private static Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);  
  
    /** aop的配置信息(增强逻辑,真实对象,切点信息) */  
    private final AdvisedSupport advised;  
  
    /** 代理接口是否有equals方法 
     */  
    private boolean equalsDefined;  
  
    /** 代理接口是否有hashCode方法 
     */  
    private boolean hashCodeDefined;  
  
  
    public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {  
        Assert.notNull(config, "AdvisedSupport must not be null");  
        if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {  
            throw new AopConfigException("No advisors and no TargetSource specified");  
        }  
        this.advised = config;  
    }  
  
  /** 获取代理*/  
    public Object getProxy() {  
        return getProxy(ClassUtils.getDefaultClassLoader());  
    }  
  
/**  至此方法结束,通过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); //找到所有接口 
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);  
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); //生成代理  
    }  
  
    /** 
     * 检查是否定义了hashCode  equals 方法  
     */  
    private void findDefinedEqualsAndHashCodeMethods(Class[] proxiedInterfaces) {  
        for (Class proxiedInterface : proxiedInterfaces) {  
            Method[] methods = proxiedInterface.getDeclaredMethods();  
            for (Method method : methods) {  
                if (AopUtils.isEqualsMethod(method)) {  
                    this.equalsDefined = true;  
                }  
                if (AopUtils.isHashCodeMethod(method)) {  
                    this.hashCodeDefined = true;  
                }  
                if (this.equalsDefined && this.hashCodeDefined) {  
                    return;  
                }  
            }  
        }  
    }  
  
    /** 
     * 这里是代理对象调用,也是jdk代理 实现的核心逻辑 
     */  
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
        MethodInvocation invocation;  
        Object oldProxy = null;  
        boolean setProxyContext = false;  
  
        TargetSource targetSource = this.advised.targetSource;  
        Class targetClass = null;  
        Object target = null;  
  
        try {  
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { //如果代理的是equlas 方法  
                return equals(args[0]);  
            }  
            if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { //如果代理的是hashCode方法  
                // The target does not implement the hashCode() method itself.  
                return hashCode();  
            }  
            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) { // 是否允许把当前代理放到AopContext中,这样可以保存在ThreadLocal中,在代码里使用AopContext.currentProxy() 获取当前代理  
                // Make invocation available if necessary.  
                oldProxy = AopContext.setCurrentProxy(proxy);  
                setProxyContext = true;  
            }  
  
            // 获取目标对象以及Class类型  
            target = targetSource.getTarget();  
            if (target != null) {  
                targetClass = target.getClass();  
            }  
  
            // 根据Method 和 targetClass 获取对应的拦截器(Advice增强封装) 这里是获取拦截逻辑的地方。(MethodMatcher 和 ClassFilter 在此处做匹配)  
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);  
  
            // 如果没有配置,或者没有匹配到任何方法,那么直接调用当前实例的方法即可  
            if (chain.isEmpty()) {  
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);  
            }  
            else {  
                // ReflectiveMethodInvocation 类封装了 增强和实例方法的调用  
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);  
                //aop的增强的植入 精华全在于此  
                retVal = invocation.proceed();  
            }  
  
            // Massage return value if necessary.  
            if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) &&  
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {  
                retVal = proxy;  
            }  
            return retVal;  
        }  
        finally {  
            if (target != null && !targetSource.isStatic()) {  
                targetSource.releaseTarget(target);  
            }  
            if (setProxyContext) {  
                AopContext.setCurrentProxy(oldProxy); //恢复currentProxy  
            }  
        }  
    }  
  
}  

代理方法调用

JdkDynamicAopProxy 实现InvocationHandler,其方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 会拦截所有通过代理调用的方法(jdk的动态代理的实现)因此invoke就是调用的入口.

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Object target = null;

        try {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                //如果目标未实现equals方法使用,统一使用这里定义的equals
                return equals(args[0]);
            }
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                //同equals
                return hashCode();
            }
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                // There is only getDecoratedClass() declared -> dispatch to proxy config.
                // 代理实现的decoratingProxy.getDecoratedClass() 用来获取代理目标的class对象
                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...
                // 如果在前面的aop基本配置中配置了opaque = false(透明化aop配置),这里对所有Advised接口中定义的方法都可以使用代理对象调用获取到aop的配置
                // 连接点调用 实际就是使用反射调用方法method.invoke(target, args)
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }
            // 下面是非特殊方法的调用
            Object retVal;

            //是否允许把当前代理放到AopContext中,这样可以保存在ThreadLocal中,在代码里使用AopContext.currentProxy() 获取当前代理 
            //通过这一步可以看到exposeProxy 的作用是可以通过AopContext在方法内部调用AopContext.currentProxy() 获取当前方法的代理对象
            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            // targetSource.getTarget()获取的就是代理目标对象
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);

            // 根据Method 和 targetClass 获取对应的拦截器(Advice增强封装) 这里是获取拦截逻辑的地方。(MethodMatcher 和 ClassFilter 在此处做匹配) 
            // 这里会涉及到切入点的判断PointcutAdvisor IntroductionAdvisor ...
            // 如pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)...  然后获取符合当前方法的Advisor
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // 如果没有配置,或者没有匹配到任何方法,那么直接调用当前实例的方法即可 
            if (chain.isEmpty()) {
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                // 没有匹配到对应的advisor就直接执行目标方法
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                // We need to create a method invocation...
                // ReflectiveMethodInvocation 类封装了 增强和实例方法的调用 
                // 要执行的目标方法就是一个连接点,这里就是将方法包装成连接点,而方面Advisors也直接包装进去了,这样方面的执行就委托给了这个连接点来实现了
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                //aop的增强的植入
                // 执行连接点(连接点中是怎么执行方面的,后面查看)
                retVal = invocation.proceed();
            }

            // Massage return value if necessary.
            // 如果目标方法返回值是this 这里进行特殊处理了一下,防止直接返回了目标对象,将返回值替换为代理对象
            // RawTargetAccess是类型标记接口,如果目标对象实现了该方法则直接返回代理目标对象
            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.
                // 这个是aop嵌套调用时满足各层都能正确得到当前方法的代理对象
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }

拦截器对象的获取。 AdvisedSupport 的 getInterceptorsAndDynamicInterceptionAdvice 方法

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) {  
        MethodCacheKey cacheKey = new MethodCacheKey(method);  
        List<Object> cached = this.methodCache.get(cacheKey);  
        if (cached == null) {  
            cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(  
                    this, method, targetClass);  
            this.methodCache.put(cacheKey, cached);  
        }  
        return cached;  
    }  

做了缓存,如果缓存不存在,通过 AdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice 来获取。 注意 这里把拦截器的获取委托的同时,仅仅提供了缓存功能,其他功能都进行了委托。

/** 此类的实现的唯一功能就是从Advised中,根据method 和 targetClass 实现拦截器的获取*/  
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {  
  
    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(  
            Advised config, Method method, Class targetClass) {  
  
        List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);  
        //判断是否有引介增强  
        boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);  
        //AdvisorAdapterRegistry 是对advice 的包装为MethodInterceptor 工具  
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();  
        for (Advisor advisor : config.getAdvisors()) {  
            if (advisor instanceof PointcutAdvisor) { //如果是PointcutAdvisor,那么要对方法和类做匹配  
                // Add it conditionally.  
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;  
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) { //如果类匹配  
                  // registry.getInterceptors(advisor) 这句话就是对Advice ->MethodInterceptor 包装  
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);  
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();  
                    if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) { //如果方法也匹配  
                        if (mm.isRuntime()) { //如果是运行时判断,会考虑参数等因素  
                            for (MethodInterceptor interceptor : interceptors) {  
                                interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));  
                            }  
                        }  
                        else { //不是运行时,直接添加  
                            interceptorList.addAll(Arrays.asList(interceptors));  
                        }  
                    }  
                }  
            }  
            else if (advisor instanceof IntroductionAdvisor) { //引介增强  
                IntroductionAdvisor ia = (IntroductionAdvisor) advisor;  
                if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) { //引介增强只需匹配类,即可  
                    Interceptor[] interceptors = registry.getInterceptors(advisor);  
                    interceptorList.addAll(Arrays.asList(interceptors));  
                }  
            }  
            else { //如果不是PointcutAdvisor 也不是 IntroductionAdvisor,那么直接包装,默认是匹配的  
                Interceptor[] interceptors = registry.getInterceptors(advisor);  
                interceptorList.addAll(Arrays.asList(interceptors));  
            }  
        }  
        return interceptorList;  
    }  
  
    /** 
     * 判断targetClass 是否匹配Advised中的任意一个Advisor 
     */  
    private static boolean hasMatchingIntroductions(Advised config, Class targetClass) {  
        for (int i = 0; i < config.getAdvisors().length; i++) {  
            Advisor advisor = config.getAdvisors()[i];  
            if (advisor instanceof IntroductionAdvisor) {  
                IntroductionAdvisor ia = (IntroductionAdvisor) advisor;  
                if (ia.getClassFilter().matches(targetClass)) {  
                    return true;  
                }  
            }  
        }  
        return false;  
    }  
  
}  

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值