• 设计模式之代理模式


    使用聚合模式实现静态代理

    本质上,动态代理是在程序运行过程中创建生成一个类并且将它加载到JVM中,通过上面的实现步骤,他是把额外的代码(spring中叫切面)植入到被代理类(方法)中以后合成一个类。与静态代理的实现是一样的.

    静态代理:在编译时创建代理类。代理类和方法都是固定的。不可改变。

    每个代理类都需要实现该接口方法。

    1、定义接口

    package cn.xiang.proxy;
    
    public interface HelloWorld {
        void sysHello();
    }

    2、实现接口,被代理类

    package cn.xiang.proxy;
    
    public class HelloWorldImpl implements HelloWorld{
    
        @Override
        public void sysHello() {
            System.out.println("HelloWordImpl --> sysHello() --> start");
            System.out.println("HelloWordImpl --> sysHello() --> end");
        }
        
    }

    3、创建代理类

    package cn.xiang.proxy;
    
    public class HelloWorldProxy implements HelloWorld{
        private HelloWorld helloWord;
        public HelloWorldProxy(HelloWorld helloword) {
            this.helloWord = helloword;
        }
    
        @Override
        public void sysHello() {
            System.out.println("HelloWordproxy sysHello() --> start");
            helloWord.sysHello();
            System.out.println("HelloWordproxy sysHello() --> end");
        }
    
    }

    4、调用代理类实现静态代理

    public class Action {
        public static void main(String[] args) {
            new HelloWorldProxy(new HelloWorldImpl2()).sysHello();
        }
    }

    动态代理

    在运行时动态创建代理对象,对象和方法都不是固定的。

    1、创建接口

    public interface HelloWorld {
        void sysHello();
    }

    2、创建被代理对象,实现接口

    public class HelloWorldImpl implements HelloWorld{
        @Override
        public void sysHello() {
            System.out.println("HelloWordImpl --> sysHello() --> start");
            System.out.println("HelloWordImpl --> sysHello() --> end");
        }
    }

    3、创建动态代理生成对象。实现InvocationHandler接口

    public class HelloWorldProxy implements InvocationHandler{
        private HelloWorld helloWord;
        public HelloWorldProxy(HelloWorld helloword) {
            this.helloWord = helloword;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("动态生成代理对象--开始");
            Object obj = method.invoke(helloWord, args);
            System.out.println("动态生成代理对象--成功");
            return obj;
        }
    }

    5、动态调用生成动态代理对象,并执行动态方法

    public class Action {
        public static void main(String[] args) {
            HelloWorldImpl hwi = new HelloWorldImpl();
            HelloWorld hw = (HelloWorld) Proxy.newProxyInstance(hwi.getClass().getClassLoader(), 
                    hwi.getClass().getInterfaces(),
                    new HelloWorldProxy(hwi));
            hw.sysHello();
        }
    }

    cglib方式

     CGLib不能对声明为final的方法和类进行代理,因为CGLib原理是动态生成被代理类的子类。

    1. 得到的代理对象其实是被代理对象的子类 
    2. 代理对象重写了被代理对象的所有方法,我们调用的时候其实是调用的被代理对象的重写方法

    1、需要导入cglib包

    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib-nodep</artifactId>
      <version>3.2.6</version>
    </dependency>

    2、创建实现类

      定义一个拦截器。在调用目标方法时,CGLib会回调MethodInterceptor接口方法拦截,来实现你自己的代理逻辑,类似于JDK中的InvocationHandler接口。

    public class HelloWorldImpl {
        public void sysHello(String name) {
            System.out.println("HelloWordImpl --> sysHello() --> start");
            System.out.println("name="+name);
            System.out.println("HelloWordImpl --> sysHello() --> end");
        }
    }

    3、创建动态代理类

    参数:Object为由CGLib动态生成的代理类实例,Method为上文中实体类所调用的被代理的方法引用,Object[]为参数值列表,MethodProxy为生成的代理类对方法的代理引用。

    返回:从代理实例的方法调用返回的值。

    其中,proxy.invokeSuper(obj,arg):

    调用代理类实例上的proxy方法的父类方法(即实体类HelloWorldImpl中对应的方法)

    public class HelloWorldProxy implements MethodInterceptor{
        @Override
        public Object intercept(Object object, 
                Method method, Object[] args, 
                MethodProxy proxy) throws Throwable {
            Object obj = proxy.invokeSuper(object, args);
            return obj;
        }
    }

    4、调用实现

    这里Enhancer类是CGLib中的一个字节码增强器,它可以方便的对你想要处理的类进行扩展,以后会经常看到它。

    首先将被代理类HelloWorldImpl设置成父类,

    然后设置拦截器HelloWorldProxy,

    最后执行enhancer.create()动态生成一个代理类,

    并从Object强制转型成父类型HelloWorldImpl。

    public class Action {
        public static void main(String[] args) {
            Enhancer en = new Enhancer();
            en.setSuperclass(HelloWorldImpl.class);
            en.setCallback( new HelloWorldProxy());
            HelloWorldImpl hw = (HelloWorldImpl)en.create();
            hw.sysHello("xiangyuqi");
        }
    }

    输出结果:

     

  • 相关阅读:
    临时表学习
    再读《黄金时代》
    shell脚本获取给定年月前一月份及后一月份
    MEMORY_TARGET not supported on this system
    2013年的总结
    windows live writer试试
    入园第一篇
    工作中经常用到的几个字符串和数组操作方法
    小程序获取用户信息失败
    前端性能优化方法概括
  • 原文地址:https://www.cnblogs.com/xiangyuqi/p/8658526.html
Copyright © 2020-2023  润新知