• AOP——代理技术


    一、如何理解代理技术

    Proxy:不用你去做,别人代替你去处理。如Windows快捷方式,又如房屋中介

    起到一个中介作用,通过代理对象,可以去掉客户不能看到的内容和服务或者添加客户需要的额外服务。

    二、代理模式

    代理模式使用代理对象完成用户请求,屏蔽用户对真实对象的访问。现实世界的代理人被授权执行当事人的一些事宜,无需当事人出面,从第三方的角度看,似乎当事人并不存在,因为他只和代理人通信。

    而事实上代理人是要有当事人的授权,并且在核心问题上还需要请示当事人。

    在软件设计中,使用代理模式的意图也很多,比如因为安全原因需要屏蔽客户端直接访问真实对象,或者在远程调用中需要使用代理类处理远程方法调用的技术细节 (如 RMI),

    也可能为了提升系统性能,对真实对象进行封装,从而达到延迟加载的目的。

    代理模式角色分为 4 种:

    1.主题接口:定义代理类和真实主题的公共对外方法,也是代理类代理真实主题的方法;

    2.真实主题:真正实现业务逻辑的类;

    3.代理类:用来代理和封装真实主题;

    4.Main:客户端,使用代理类和主题接口完成一些工作。

    三、具体使用

    1.静态代理

    /**
     * Created by solverpeng on 2016/6/29.
     */
    public interface Factory {
    
        void say();
    
        void produce();
    
    }
    Factory
    /**
     * NikeFatory
     *
     * @author solverpeng
     * @create 2016-06-29-11:28
     */
    public class NikeFactory implements Factory {
        @Override
        public void say() {
            System.out.println("我要开始生产了!");
        }
    
        @Override
        public void produce() {
            System.out.println("正在生产Nike衣服!");
        }
    }
    NikeFactory
    /**
     * NikeFactoryProxy
     *
     * @author solverpeng
     * @create 2016-06-29-11:30
     */
    public class NikeFactoryProxy implements Factory {
        private NikeFactory nikeFactory;
    
        public NikeFactoryProxy() {
            this.nikeFactory = new NikeFactory();
        }
        @Override
        public void say() {
            before();
            nikeFactory.say();
            after();
        }
    
        @Override
        public void produce() {
            before();
            nikeFactory.produce();
            after();
        }
    
        private void after() {
            System.out.println("大家做的不错!");
        }
    
        private void before() {
            System.out.println("在正式开始生产之前,我要说两句!");
        }
    }
    NikeFactoryProxy
    @Test
        public void testStaticProxy() {
            NikeFactoryProxy nikeFactoryProxy = new NikeFactoryProxy();
            nikeFactoryProxy.say();
            nikeFactoryProxy.produce();
        }
    testStaticProxy

    2.JDK动态代理

    @Test
        public void testJDKProxy() {
            Factory proxyInstance = (Factory) Proxy.newProxyInstance(NikeFactory.class.getClassLoader(), NikeFactory.class.getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    return method.invoke(NikeFactory.class.newInstance(), args);
                }
            });
            proxyInstance.say();
            proxyInstance.produce();
        }
    testJDKProxy
    /**
     * 通用的代理生产工厂
     *
     * @author solverpeng
     * @create 2016-06-29-11:45
     */
    public class DynamicProxy implements InvocationHandler {
    
        private Object target;
    
        public DynamicProxy(Object target) {
            this.target = target;
        }
    
        @SuppressWarnings("unchecked")
        public <T> T getProxy() {
            return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return method.invoke(target, args);
        }
    
    }
    DynamicProxy
    @Test
        public void testJDKProxy2() {
            DynamicProxy dynamicProxy = new DynamicProxy(new NikeFactory());
            Factory proxy =  dynamicProxy.getProxy();
            proxy.say();
            proxy.produce();
        }
    testJDKProxy2

    3.CGLIB动态代理(需要额外导入cglib包)

    /**
     * CglibProxy
     *
     * @author solverpeng
     * @create 2016-06-29-14:40
     */
    public class CglibProxy implements MethodInterceptor{
        private static CglibProxy instance = new CglibProxy();
    
        public CglibProxy() {
        }
    
        public static CglibProxy getInstance() {
            return instance;
        }
    
        @SuppressWarnings("unchecked")
        public <T> T getProxy(Class<T> cls) {
            return (T)Enhancer.create(cls, this);
        }
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            return methodProxy.invokeSuper(o, objects);
        }
    }
    CglibProxy
    @Test
        public void testCglibProxy2() {
            NikeFactory proxy = CglibProxy.getInstance().getProxy(NikeFactory.class);
            proxy.say();
            proxy.produce();
        }
    testCglibProxy2

    四、总结

    JDK动态代理获取代理的是通过:Proxy.newProxyInstance() 方法来获取的,需要一个 InvocationHandler 类型的对象。传入的参数为目标对象。

    CGLIB 动态代理获取代理是通过:Enhancer.create() 方法,需要一个 MethodInterceptor 类型的对象。

    在使用 CGLIB 包的时候,可能会出现 java.lang.ClassNotFoundException: org.objectweb.asm.Type 的异常,导入 spring 下的 cglib 包就ok。

  • 相关阅读:
    关于给Tomcat设置maxPostSize的问题
    完美激活PyCharm教程
    Tomcat +Nginx+Redis实现session共享
    python 上传多文件
    吸引注意力的动画
    Create React App 安装less 报错
    2020软件工程作业01
    yum用法
    rpm包的管理
    共享依赖库的误移或误删解决办法
  • 原文地址:https://www.cnblogs.com/solverpeng/p/5627124.html
Copyright © 2020-2023  润新知