代理模式

来源:互联网 发布:淘宝账号被盗 支付宝 编辑:程序博客网 时间:2024/06/05 16:40

(一)什么是代理模式
通过引入一个代理对象,来操作、控制、访问真实对象。
给目标对象提供一个代理,并由代理对象控制对目标对象的引用。
(二)静态代理
1)模式结构
这里写图片描述

2)角色
Subject: 抽象主题角色
RealSubject: 真实主题角色
Proxy: 代理主题角色
3)简化的结构图
代理模式示意结构图比较简单,一般可以简化为如下图所示,但是在现实中要复杂很多。
这里写图片描述
4)代码示例:

//接口public interface IUserDao {    void save();}
//目标对象;真实对象;要被代理的对象public class UserDao implements IUserDao {    @Override    public void save() {        System.out.println("-----数据已经保存了-----");    }}
//代理对象,静态代理public class Proxy implements IUserDao {    //把目标对象作为代理类的属性    private IUserDao target;    //采用聚合的方式,把目标对象通过构造参数传过来    public Proxy(IUserDao target) {        super();        this.target = target;    }    @Override    public void save() {        System.out.println("开始事务...");        target.save();        System.out.println("提交事务...");    }}
//客户端测试public class MyTest {    public static void main(String[] args) {        //目标对象        IUserDao target=new UserDao();        //把目标对象通过构造参数传给代理对象        Proxy proxy=new Proxy(target);        proxy.save();    }}

(三)JDK动态代理
1)代码示例

//接口public interface UserService {    void add();}
//目标对象;被代理对象;需要实现接口public class UserServiceImpl implements UserService {    @Override    public void add() {        System.out.println("添加数据");    }}
//把目标对象传给这个类,并通过这个类的getProxy方法拿到目标对象的代理对象public class ProxyFactory {    //维护一个目标对象    private Object target;    public ProxyFactory(Object target) {        super();        this.target = target;    }    //创建一个InvocationHandler对象    private InvocationHandler handler=new InvocationHandler() {        @Override        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {            System.out.println("before...");            Object result=method.invoke(target, args);            System.out.println("after...");            return result;        }    };    //为目标对象创建代理对象    public Object getProxy(){        return Proxy.newProxyInstance(                target.getClass().getClassLoader(),                 target.getClass().getInterfaces(),                 handler);    }}
//客户端测试类public class MyTest {    public static void main(String[] args) {        //目标对象        UserService service=new UserServiceImpl();        //获取代理对象        //该代理对象一定会实现目标对象的接口UserService,因此可以强转        UserService proxy=(UserService)new ProxyFactory(service).getProxy();        proxy.add();    }}

注意:在JDK动态代理中,目标对象一定要实现接口,否则不能使用JDK动态代理
(四)cglib动态代理
思考:上面的静态代理和JDK动态代理,都要求目标对象实现某个接口。如果目标对象没有实现任何接口,那该怎么办呢?这时候应该使用cglib动态代理。
1)cglib动态代理,为指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
2)需要引入cglib的jar包,由于Spring的核心包中已经包括了cglib功能,所以直接引入spring-core-4.0.6.RELEASE.jar即可。
3)代码示例

//目标对象,未实现任何接口public class UserDao {      public void print(){        System.out.println("hello world");    }}
//把目标对象传给这个类,并且通过这个类获取目标对象的代理对象public class Cglib implements MethodInterceptor{    //维护目标对象    private Object target;    public Cglib(Object target) {        super();        this.target = target;    }    //为目标对象创建代理对象    public Object getProxy(){        //工具类        Enhancer en=new Enhancer();        //设置父类        en.setSuperclass(target.getClass());        //设置回调函数        en.setCallback(this);        //创建代理对象        return en.create();    }    @Override    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {        System.out.println("开始事务...");        Object result=method.invoke(target, args);        System.out.println("提交事务...");        return result;    }   }
//客户端测试类public class MyTest {    public static void main(String[] args) {        //目标对象        UserDao dao=new UserDao();        //获取代理对象        //代理类是目标类UserDao的子类,因此可以强转        UserDao proxy=(UserDao)new Cglib(dao).getProxy();        proxy.print();    }}
原创粉丝点击