博客
关于我
代理模式(结构性模式)
阅读量:156 次
发布时间:2019-02-28

本文共 4439 字,大约阅读时间需要 14 分钟。

Proxy Pattern: Provide a surrogate or placeholder for another object to control access to it.

代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。

代理模式结构图

在这里插入图片描述

1.静态代理

静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类.

package Static;public interface UserDao {       void save();}
package Static;public class UserDaoImpl implements UserDao {       @Override    public void save() {           System.out.println("----已经保存数据!----");    }}
package Static;public class UserDaoProxy implements UserDao{       //接收保存目标对象    private UserDao target;    public UserDaoProxy(UserDao target){           this.target=target;    }    public void save() {           System.out.println("开始事务...");        target.save();//执行目标对象的方法        System.out.println("提交事务...");    }}
package Static;public class TestMain {       public static void main(String[] args) {           //目标对象        UserDao userDao=new UserDaoImpl();        UserDaoProxy userDaoProx=new UserDaoProxy(userDao);        userDaoProx.save();    }}

缺点:

因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.

2.动态代理

1

package Static;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 创建动态代理对象 * 动态代理不需要实现接口,但是需要指定接口类型 */public class ProxyFactory {       //维护一个目标对象    private Object target;    public ProxyFactory(Object target){           this.target=target;    }    //给目标对象生成代理对象    public Object getProxyInstance(){           return Proxy.newProxyInstance(                target.getClass().getClassLoader(),                target.getClass().getInterfaces(),                new InvocationHandler() {                       @Override                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                           System.out.println("开始事务2");                        //执行目标对象方法                        Object returnValue = method.invoke(target, args);                        System.out.println("提交事务2");                        return returnValue;                    }                }        );    }}
package Static;public class App {       public static void main(String[] args) {           // 目标对象        UserDao target=new UserDaoImpl();        // 【原始的类型 class Static.UserDaoImpl】        System.out.println(target.getClass());        // 给目标对象,创建代理对象        UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance();        // class com.sun.proxy.$Proxy0  内存中动态生成的代理对象        System.out.println(proxy.getClass());        // 执行方法   【代理对象】        proxy.save();    }}

2.Cglib代理

上面的静态代理和动态代理模式都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理

在Spring的AOP编程中:

如果加入容器的目标对象有实现接口,用JDK代理
如果目标对象没有实现接口,用Cglib代理

package Cglib;public class UserDao {       public void save() {           System.out.println("----已经保存数据!----");    }}
package Cglib;import org.springframework.cglib.proxy.Enhancer;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/** * Cglib子类代理工厂 * 对UserDao在内存中动态构建一个子类对象 *///1.需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,// 所以直接引入spring-core-3.2.5.jar即可.public class ProxyFactory implements MethodInterceptor {       //维护目标对象    private Object target;    public ProxyFactory(Object target) {           this.target = target;    }    //给目标对象创建一个代理对象    public Object getProxyInstance(){           //1.工具类        Enhancer en = new Enhancer();        //2.设置父类        en.setSuperclass(target.getClass());        //3.设置回调函数        en.setCallback(this);        //4.创建子类(代理对象)        return en.create();    }    @Override    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {           System.out.println("开始事务...");        //执行目标对象的方法        Object returnValue = method.invoke(target, args);        System.out.println("提交事务...");        return returnValue;    }}
package Cglib;import Static.ProxyFactory;import Static.UserDao;import Static.UserDaoImpl;public class App {       public static void main(String[] args) {           // 目标对象        Static.UserDao target=new UserDaoImpl();        // 【原始的类型 class Static.UserDaoImpl】        System.out.println(target.getClass());        //代理对象        UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance(); // class com.sun.proxy.$Proxy0  内存中动态生成的代理对象        System.out.println(proxy.getClass());        // 执行方法   【代理对象】        proxy.save();    }}

转载地址:http://pwrd.baihongyu.com/

你可能感兴趣的文章
mysql 数据库备份及ibdata1的瘦身
查看>>
MySQL 数据库备份种类以及常用备份工具汇总
查看>>
mysql 数据库存储引擎怎么选择?快来看看性能测试吧
查看>>
MySQL 数据库操作指南:学习如何使用 Python 进行增删改查操作
查看>>
MySQL 数据库的高可用性分析
查看>>
MySQL 数据库设计总结
查看>>
Mysql 数据库重置ID排序
查看>>
Mysql 数据类型一日期
查看>>
MySQL 数据类型和属性
查看>>
mysql 敲错命令 想取消怎么办?
查看>>
Mysql 整形列的字节与存储范围
查看>>
mysql 断电数据损坏,无法启动
查看>>
MySQL 日期时间类型的选择
查看>>
Mysql 时间操作(当天,昨天,7天,30天,半年,全年,季度)
查看>>
MySQL 是如何加锁的?
查看>>
MySQL 是怎样运行的 - InnoDB数据页结构
查看>>
mysql 更新子表_mysql 在update中实现子查询的方式
查看>>
MySQL 有什么优点?
查看>>
mysql 权限整理记录
查看>>
mysql 权限登录问题:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)
查看>>