zoukankan      html  css  js  c++  java
  • spring aop 的代理工厂

    参考 https://docs.spring.io/spring/docs/4.3.11.RELEASE/spring-framework-reference/htmlsingle/#aop-understanding-aop-proxies

    package org.springframework.aop.framework

    public class ProxyFactory extends ProxyCreatorSupport {
    ...
    }
    public class ProxyCreatorSupport extends AdvisedSupport {
    
        private AopProxyFactory aopProxyFactory;
    
        ...
    
    
        /**
         * Create a new ProxyCreatorSupport instance.
         */
        public ProxyCreatorSupport() {
            this.aopProxyFactory = new DefaultAopProxyFactory();
        }
    
        ...
    }
    public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    
        @Override
        public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
            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() || Proxy.isProxyClass(targetClass)) {
                    return new JdkDynamicAopProxy(config);
                }
                return new ObjenesisCglibAopProxy(config);
            }
            else {
                return new JdkDynamicAopProxy(config);
            }
        }
    
        ...
    
    }
    boolean java.lang.reflect.Proxy.isProxyClass(Class<?> cl)
    
    
    Returns true if and only if the specified class was dynamically generated to be a proxy class using the getProxyClass method or the newProxyInstance method. 
    
    The reliability of this method is important for the ability to use it to make security decisions, so its implementation should not just test if the class in question extends Proxy.
    
    Parameters:
    cl the class to test
    Returns:
    true if the class is a proxy class and false otherwise
    Throws:
    NullPointerException - if cl is null

    JDK 示例

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.aop.framework.ProxyFactory;
    
    public class Main {
        public static void main(String[] args) {
    
            ProxyFactory factory = new ProxyFactory(new SimplePojo());
            factory.addInterface(Pojo.class);
            factory.addAdvice(new SomeAdvice());
            Pojo pojo = (Pojo) factory.getProxy();
    
            // this is a method call on the proxy!
            pojo.foo();
        }
    }
    
    class SimplePojo implements Pojo {
    
        @Override
        public void foo() {
            // this next method invocation is a direct call on the 'this' reference
            this.bar();
        }
    
        @Override
        public void bar() {
            // some logic...
            System.out.println("barrrrrrrr");
        }
    
    }
    
    interface Pojo {
        public void foo();
    
        public void bar();
    }
    
    class SomeAdvice implements MethodInterceptor {
    
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            String name = invocation.getMethod().getName();
            System.out.println(name + " start");
            Object proceed = invocation.proceed();
            System.out.println(name + " end");
            return proceed;
        }
    
    }

    运行结果:

    foo start
    barrrrrrrr
    foo end

    通过代理才会执行advise , 自调用(self-invocation 例如 this.bar())不会执行代理的advise 。

    解决方式有两种,其一:

    暴露代理(不推荐使用)

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.aop.framework.AopContext;
    import org.springframework.aop.framework.ProxyFactory;
    
    public class Main {
        public static void main(String[] args) {
    
            ProxyFactory factory = new ProxyFactory(new SimplePojo());
            factory.addInterface(Pojo.class);
            factory.addAdvice(new SomeAdvice());
            factory.setExposeProxy(true);
            Pojo pojo = (Pojo) factory.getProxy();
    
            // this is a method call on the proxy!
            pojo.foo();
        }
    }
    
    class SimplePojo implements Pojo {
    
        @Override
        public void foo() {
            // this works, but... gah!
            ((Pojo) AopContext.currentProxy()).bar();
        }
    
        @Override
        public void bar() {
            // some logic...
            System.out.println("barrrrrrrr");
        }
    
    }
    
    interface Pojo {
        public void foo();
    
        public void bar();
    }
    
    class SomeAdvice implements MethodInterceptor {
    
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            String name = invocation.getMethod().getName();
            System.out.println(name + " start");
            Object proceed = invocation.proceed();
            System.out.println(name + " end");
            return proceed;
        }
    
    }

    运行结果:

    foo start
    bar start
    barrrrrrrr
    bar end
    foo end

    其二:

    抽新类,避免自调用

    CGLIB 示例

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.aop.framework.ProxyFactory;
    
    public class Main {
        public static void main(String[] args) {
    
            ProxyFactory factory = new ProxyFactory(new SimplePojo());
            factory.addAdvice(new SomeAdvice());
            SimplePojo pojo = (SimplePojo) factory.getProxy();
    
            // this is a method call on the proxy!
            pojo.foo();
        }
    }
    
    class SimplePojo {
    
        public void foo() {
            this.bar();
        }
    
        public void bar() {
            // some logic...
            System.out.println("barrrrrrrr");
        }
    
    }
    
    
    class SomeAdvice implements MethodInterceptor {
    
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            String name = invocation.getMethod().getName();
            System.out.println(name + " start");
            Object proceed = invocation.proceed();
            System.out.println(name + " end");
            return proceed;
        }
    
    }

    运行结果:

    foo start
    barrrrrrrr
    foo end

    暴露代理同JDK 动态代理

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.aop.framework.AopContext;
    import org.springframework.aop.framework.ProxyFactory;
    
    public class Main {
        public static void main(String[] args) {
    
            ProxyFactory factory = new ProxyFactory(new SimplePojo());
            factory.addAdvice(new SomeAdvice());
            factory.setExposeProxy(true);
            SimplePojo pojo = (SimplePojo) factory.getProxy();
    
            // this is a method call on the proxy!
            pojo.foo();
        }
    }
    
    class SimplePojo {
    
        public void foo() {
            ((SimplePojo) AopContext.currentProxy()).bar();
        }
    
        public void bar() {
            // some logic...
            System.out.println("barrrrrrrr");
        }
    
    }
    
    
    class SomeAdvice implements MethodInterceptor {
    
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            String name = invocation.getMethod().getName();
            System.out.println(name + " start");
            Object proceed = invocation.proceed();
            System.out.println(name + " end");
            return proceed;
        }
    
    }

    运行结果:

    foo start
    bar start
    barrrrrrrr
    bar end
    foo end

    相关内容

    @Transactional 为什么会失效

    https://docs.spring.io/spring/docs/4.3.11.RELEASE/spring-framework-reference/htmlsingle/#transaction-declarative-annotations

    Method visibility and @Transactional

    When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.

     

    import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.springframework.aop.framework.ProxyFactory;
    public class Main {public static void main(String[] args) {
    ProxyFactory factory = new ProxyFactory(new SimplePojo());factory.addInterface(Pojo.class);factory.addAdvice(new SomeAdvice());factory.setExposeProxy(true);Pojo pojo = (Pojo) factory.getProxy();
    // this is a method call on the proxy!pojo.foo();}}
    class SimplePojo implements Pojo {
    @Overridepublic void foo() {// this next method invocation is a direct call on the 'this' referencethis.bar();}
    @Overridepublic void bar() {// some logic...System.out.println("barrrrrrrr");}
    }
    interface Pojo {public void foo();
    public void bar();}
    class SomeAdvice implements MethodInterceptor {
    @Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {String name = invocation.getMethod().getName();System.out.println(name + " start");Object proceed = invocation.proceed();System.out.println(name + " end");return proceed;}
    }

  • 相关阅读:
    Matlab中imagesc用法
    codevs 3160 最长公共子串(SAM)
    spoj 7258 SUBLEX(SAM,名次)
    spoj 1812 LCS2(SAM+DP)
    spoj 8222 Substrings(后缀自动机+DP)
    tyvj P1519 博彩游戏(AC自动机+DP滚动数组)
    bzoj 1030 [JSOI2007]文本生成器(AC自动机+DP)
    vijos P1459 车展(Treap,中位数)
    bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)
    bzoj 1483 [HNOI2009]梦幻布丁(链表+启发式合并)
  • 原文地址:https://www.cnblogs.com/zno2/p/9182456.html
Copyright © 2011-2022 走看看