## 代理模式概念 * 什么是代理模式 > 代理模式是指为其他对象提供一种代理,达到控制这个对象的访问;简单理解,现在有一个目标对象,客户端需要用到这个目标对象,但是客户端不能直接调用目标对象,这个时候,定义一个代理对象,客户端通过代理对象,访问到目标对象;实际上代理对象和目标对象之间起的是中介作用。 * 举例说明代理模式的概念 > 比如现在张三想要买李四的房子,但是张三没有李四的联系方式,不能直接找李四买房子,这个时候,张三就可以找房屋中介,由中介去联系张三,在这个例子中,可以把李四看作是目标对象,房屋中介是代理对象; ## 静态代理 * 静态代理概念 > 由上面的概念可以得出,在代理模式中,需要有目标对象和代理对象,静态代理的关键在于,需要定义顶层接口,并且目标对象和代理对象都需要实现该接口,以此来实现静态代理模式。 * 实现静态代理事例 1)定义一个顶层接口 ```java public interface StaticProxy { //定义一个抽象方法 public void insertData(); } ``` 2)定义一个目标类对象,目标对象需要实现上面的接口StaticProxy ```java public class Target implements StaticProxy{ @Override public void insertData() { System.out.println("目标对象正在执行新增数据的方法"); } } ``` 3)定义一个代理对象,根据静态代理的需求,代理对象需要和目标对象实现同一个接口 ```java public class Agent implements StaticProxy{ //声明一个目标对象 private Target target; //使用构造方法初始化目标对象 public Agent(Target target){ this.target = target; } @Override public void insertData() { System.out.println("代理对象,在对新增数据方法进行局部扩展"); //在这里调用目标对象中的方法 target.insertData(); } } ``` 4)测试静态代理方式 ```java public class Test { public static void main(String[] args) { //创建目标对象 Target target = new Target(); //创建代理对象 Agent agent = new Agent(target); //通过代理对象调用新增数据的方法insertData agent.insertData(); } } ``` 5)测试结果  * 静态代理说明 > 代码设计:在目标对象中的insertData方法,只是输出了“目标对象正在执行新增的方法”这句话,然后在通过代理对象后,因为都实现了StaticProxy接口,因此代理对象也需要重写insertData方法,只不过这里的insertData比起目标对象中的方法,做了扩展,之后再由传入的目标对象调用insertData方法 > > 测试方法:在测试方法的时候,需要将目标对象传递给代理对象,然后通过代理对象调用insertData方法。 > > 测试效果:既调用了代理对象扩展后的方法,也执行了目标对象中的代码 * 静态代理作用 > 静态代理作用就是代理模式的作用,在不修改原目标中代码的情况下,对目标对象的已有方法进行扩展,而且还能不影响原目标对象的作用。 * 静态代理的缺点 > 从上述代码可以看出,静态代理要求目标对象和代理对象都需要实现同一个接口,那么对于没有实现接口的类,不能代理;再者,当原目标较为复杂,代理对象就难以操作。 ## JDK封装的代理模式 * JDK的代理模式概念 > 在Java的动态代理机制中,有两个重要的接口和类,接口是InvoactionHandler,类是Proxy;jdk的动态代理模式中,代理类都必须实现InvocationHandler这个接口,并且么个代理类的实例都关联到一个Handler,通过代理对象调用一个方法的时候,这个方法的调用会转发由InvocationHandler这个接口的invoke方法来调用。 * 代码演示动态代理 1)定义一个顶层接口DataMapper ```java public interface DataMapper { //定义抽象方法新增数据 public void insertData(); } ``` 2)定义目标对象,需要实现接口DataMapper ```java public class Target implements DataMapper{ @Override public void insertData() { System.out.println("目标对象新增数据"); } } ``` 3)定义代理对象,需要实现InvocationHandler接口 ```java public class Agent implements InvocationHandler { //声明接口 private DataMapper dataMapper; //返回代理对象 public Object getInstance(DataMapper dataMapper) throws Exception{ this.dataMapper = dataMapper; Class clazz = dataMapper.getClass(); return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this); } /** * 执行invoke方法 * @param proxy 代理对象 * @param method 目标对象方法 * @param args 目标对象方法的参数列表 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //调用前置增强 before(); //这是执行目标对象 Object obj = method.invoke(this.dataMapper,args); //嗲用后置增强 after(); return obj; } //自定义 public void before(){ System.out.println("代理对象进行前置增强,比如新增数据之前先开启事务"); } //自定义 public void after(){ System.out.println("代理对象进行后置增强,比如新增数据之后,提交事务"); } } ``` 4)测试类 ```java public class Test { public static void main(String[] args) throws Exception{ //创建目标对象 DataMapper dataMapper = (DataMapper) new Agent().getInstance(new Target()); dataMapper.insertData(); } } ``` * 测试结果  * jdk动态代理说明 > 上面的事例中,DataMappr是顶层接口;Target是目标类;Agent类是代理类;Test作为测试类,可以从结果集中可以看出,创建的是代理对象Agent,将目标对象传递给代理对象,通过代理对象调用insertData方法,除了将目标对象中代码执行了,也将前置增强和后置增强执行了。 ## CGLIB动态代理 * CGLIB动态代理概念 > CGLIB动态代理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术,拦截所有的父类方法的调用, * cglib动态代理事例 1)定义一个目标类, ```java public class Target{ public void insertData() { System.out.println("目标对象新增方法"); } } ``` 2)定义一个代理类,需要实现cglib的接口MethodInterceptor ```java public class Agent implements MethodInterceptor { //获取代理对象 public Object getInstance(Class clazz) throws Exception{ //创建字节码增强器,用来对被代理的类扩展 Enhancer enhancer = new Enhancer(); //通知cglib,生成的子类需要继承那个父类 enhancer.setSuperclass(clazz); //设置回调 enhancer.setCallback(this); //创建对象 Object obj = enhancer.create(); return obj; } /** * * @param obj 生成的子类对象 * @param method 被拦截的方法 * @param args 被拦截方法的参数 * @param proxy 触发父类方法的对象 * @return * @throws Throwable */ @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { before(); //这里是调用invokeSuper()方法,不能调用invoke方法 Object object = proxy.invokeSuper(obj, args); after(); return object; } //前置增强方法 public void before(){ System.out.println("前置增强方法"); } //后置增强方法 public void after(){ System.out.println("后置增强方法"); } } ``` 3)测试类 ```java public class Test { public static void main(String[] args) throws Exception { Target target = (Target) new Agent().getInstance(Target.class); target.insertData(); } } ``` * 测试结果  ## 代理模式总结 * 三种代理模式的区别 ```text 1)静态代理:静态代理要求目标对象和代理对象都实现同一个接口,并且如果目标对象的上层接口代码较为复杂,则代理对象也会变得复杂 2)jdk动态代理:在静态代理的基础上,jdk的实现只需要要求目标对象必须有实现的接口即可,如果是普通类,jdk则不能完成代理 3)cglib动态代理:比起jdk动态代理,cglib代理可以代理任何类,对目标类没有特殊的要求,运用较为灵活 ``` 以上是三种代理模式的简单实现,至于原理和源码分析,本篇文章暂不做更多内容,后续再继续了解! **关注公众号:源码说** 
微信关注我们
原文链接:https://blog.51cto.com/u_14822748/2907487
转载内容版权归作者及来源网站所有!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
相关文章
发表评论
资源下载
更多资源优质分享Android(本站安卓app)
近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。
Mario,低调大师唯一一个Java游戏作品
马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。
Oracle Database,又名Oracle RDBMS
Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的、适应高吞吐量的数据库方案。
Java Development Kit(Java开发工具)
JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。