博客
关于我
代理模式(结构性模式)
阅读量: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/

你可能感兴趣的文章
mysql5.6 TIME,DATETIME,TIMESTAMP
查看>>
mysql5.6.21重置数据库的root密码
查看>>
Mysql5.6主从复制-基于binlog
查看>>
MySQL5.6忘记root密码(win平台)
查看>>
MySQL5.6的Linux安装shell脚本之二进制安装(一)
查看>>
MySQL5.6的zip包安装教程
查看>>
mysql5.7 for windows_MySQL 5.7 for Windows 解压缩版配置安装
查看>>
Webpack 基本环境搭建
查看>>
mysql5.7 安装版 表不能输入汉字解决方案
查看>>
MySQL5.7.18主从复制搭建(一主一从)
查看>>
MySQL5.7.19-win64安装启动
查看>>
mysql5.7.19安装图解_mysql5.7.19 winx64解压缩版安装配置教程
查看>>
MySQL5.7.37windows解压版的安装使用
查看>>
mysql5.7免费下载地址
查看>>
mysql5.7命令总结
查看>>
mysql5.7安装
查看>>
mysql5.7性能调优my.ini
查看>>
MySQL5.7新增Performance Schema表
查看>>
Mysql5.7深入学习 1.MySQL 5.7 中的新增功能
查看>>
Webpack 之 basic chunk graph
查看>>