设计模式之代理模式

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

本质上,动态代理是在程序运行过程中创建生成一个类并且将它加载到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");
    }
}

输出结果:

 

 

posted @ 2018-03-27 17:06  项羽齐  阅读(179)  评论(0编辑  收藏  举报