首页 > spring > AOP的设计思想

AOP的设计思想

作者:bin

一、静态代理:
静态代理就是实现一个「新类」他和「原类」实现同一个接口,使用时替换「原类」以达到增强的效果

package com.zengbingo.proxyStatic;
public class proxyStatic {
    public static void main(String[] args) {
        A a = new A();
        B b = new B(a);
        b.print();
    }
    /**
     * 「原类」
     * 实现print
     */
    public static class A implements print{

        @Override
        public void print(){
            System.out.println("A你好");
        }
    }
    
    /**
     * 「新类」
     * 实现同一个接口print
     */
    public static class B implements print{
        //构造方法传入「原类」
        B(A source){  a=source;  }
        public static A a;
        
        /**
         * 增强
         */
        @Override
        public void print(){
            System.out.println("B之前");
            a.print();
            System.out.println("B之后");
        }
    }
    public interface print{
        public void print();
    }
}

静态代理就是需要在每个需要被代理的「原类」都实现一个「新类」,但是一些重复的功能我们可能不希望重复写,例如上面的例子,例如还有一个C类也需要被增强,你就要在构造更多的B来满足要求


二、动态代理
动态代理即将代理类的生层过程抽出来,由代理对象生成器去生成增强的代理类。
动态代理一般有两种方式,一种基于反射实现的「JDK」、另一种基于字节码生成的CGLIB代理。
1.JDK代理
JDK代理类的生成交给Proxy类来实现,JDK代理通过反射实现来一个代理类,所有的方法都通过InvocationHandler的invoker进行拦截

public class JdkProxy {

    public static void main(String[] arg) {
        A real1 = new A();
        ProxyAHandler proxyAHandler = new ProxyAHandler(real1);

        /**
         * 生成代理类的过程交给Proxy去做
         */
        Print proxyA = (Print) Proxy.newProxyInstance(
                A.class.getClassLoader(),
                new Class[]{Print.class},
                proxyAHandler);
        proxyA.print();
    }


    private static class A implements Print {
        @Override
        public void print() {
            System.out.println("A你好");
            selfTransfer();
        }
        @Override
        public void selfTransfer(){
            System.out.println("A我在内部被调用不会被代理");
        }
    }

    private static class ProxyAHandler implements InvocationHandler {
        public ProxyAHandler(Object source) {
            this.source = source;
        }
        private Object source;

        /**
         * 不管是什么方法,都会被代理,除了类内部自己调用,因为类内部自己调用,没有走到代理类
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println(method.getName() + ",invoke前");
            Object o = method.invoke(source, args);
            System.out.println(method.getName() + ",invoke后");
            return o;
        }
    }

    private interface Print {
       void print();
       //自己调自己
       void selfTransfer();
    }
}
print,invoke前
A你好
A我在内部被调用不会被代理
print,invoke后

2.CGLIB代理
通过使用Enhancer方法,实现一个继承「原类」的「新类」,对「原类」方法进行拦截增强,代码如下:

public class CglibProxy {
    public static void main(String[] arg) {
        Enhancer enhancer = new Enhancer();
        //设置需要继承哪个类
        enhancer.setSuperclass(A.class);
        //设置拦截的方法
        enhancer.setCallback(new AInterceptorImpl());
        //构造代理对象
        A a =  (A)enhancer.create();
        a.print();
    }

    public static class A{
        public void print() {
            System.out.println("A你好");
            selfTransfer();
        }
        public void selfTransfer(){
            System.out.println("A在内部也会被代理");
        }
    }

    private static class AInterceptorImpl implements MethodInterceptor {
        @Override
        public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println(method.getName() + ",invoke前");
            Object res = methodProxy.invokeSuper(object, args);
            System.out.println(method.getName() + ",invoke后");

            return res;
        }
    }
}

输出

print,invoke前
A你好
selfTransfer,invoke前
A在内部也会被代理
selfTransfer,invoke后
print,invoke后

3.spring 中的CGLIB代理
我们知道spring中的AOP,在类内部调用时是不会触发拦截的,上面的JDK是满足要求的,CGLIB是不满足要求的。那么spring中的CGLIB是如何实现类内部调用不触发的呢?

public class SpringCglibProxy {
    public static void main(String[] arg) {
        Enhancer enhancer = new Enhancer();
        //设置需要继承哪个类
        enhancer.setSuperclass(A.class);
        //设置拦截的方法
        A sourceA = new A();
        enhancer.setCallback(new AInterceptorImpl(sourceA));
        //构造代理对象
        A a =  (A)enhancer.create();
        a.print();
    }

    public static class A{
        public void print() {
            System.out.println("A你好");
            selfTransfer();
        }
        public void selfTransfer(){
            System.out.println("A在内部不会被代理");
        }
    }

    private static class AInterceptorImpl implements MethodInterceptor {

        //类似JDK,将source类传入使用
        private A a;
        AInterceptorImpl(A source){
            a=source;
        }

        @Override
        public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println(method.getName() + ",invoke前");
            //invoke指定类,而不是super类
            Object res = methodProxy.invoke(a, args);
            System.out.println(method.getName() + ",invoke后");

            return res;
        }
    }
}

输出:

print,invoke前
A你好
A在内部不会被代理
print,invoke后

您必须 [ 登录 ] 才能发表留言!