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

你可能感兴趣的文章
Nginx配置好ssl,但$_SERVER[‘HTTPS‘]取不到值
查看>>
Nginx配置如何一键生成
查看>>
Nginx配置实例-动静分离实例:搭建静态资源服务器
查看>>
Nginx配置实例-反向代理实例:根据访问的路径跳转到不同端口的服务中
查看>>
Nginx配置实例-负载均衡实例:平均访问多台服务器
查看>>
Nginx配置文件nginx.conf中文详解(总结)
查看>>
nginx配置详解、端口重定向和504
查看>>
Nginx配置负载均衡到后台网关集群
查看>>
Nginx配置限流,技能拉满!
查看>>
Nginx面试三连问:Nginx如何工作?负载均衡策略有哪些?如何限流?
查看>>
Nginx:NginxConfig可视化配置工具安装
查看>>
ngModelController
查看>>
ngrok | 内网穿透,支持 HTTPS、国内访问、静态域名
查看>>
ngrok内网穿透可以实现资源共享吗?快解析更加简洁
查看>>
NHibernate学习[1]
查看>>
NHibernate异常:No persister for的解决办法
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_日期类型_以及null数据同步处理补充---大数据之Nifi工作笔记0057
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_补充_更新时如果目标表中不存在记录就改为插入数据_Postgresql_Hbase也适用---大数据之Nifi工作笔记0059
查看>>
NIFI1.21.0_NIFI和hadoop蹦了_200G集群磁盘又满了_Jps看不到进程了_Unable to write in /tmp. Aborting----大数据之Nifi工作笔记0052
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增删改数据分发及删除数据实时同步_通过分页解决变更记录过大问题_02----大数据之Nifi工作笔记0054
查看>>