java之代理设计模式

代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。

这里写图片描述

静态代理

  1. 定义一个接口
package cn.itcast.proxy.sh;public interface PersonDao {public void savePerson();public void updatePerson();public void deletePerson();
}

2、 目标类

package cn.itcast.proxy.sh;public class PersonDaoImpl implements PersonDao{public void deletePerson() {System.out.println("delete person");}public void savePerson() {System.out.println("save person");}public void updatePerson() {System.out.println("update person");}
}

3、代理类,包含了目标类和一些额外的操作

package cn.itcast.proxy.sh;public class PersonDaoProxy implements PersonDao{private PersonDao personDao;private Transaction transaction;public PersonDaoProxy(PersonDao personDao,Transaction transactions){this.personDao = personDao;this.transaction = transactions;}public void deletePerson() {this.transaction.beginTransaction();this.personDao.deletePerson();this.transaction.commit();}public void savePerson() {this.transaction.beginTransaction();this.personDao.savePerson();this.transaction.commit();}public void updatePerson() {this.transaction.beginTransaction();this.personDao.updatePerson();this.transaction.commit();}
}

4、使用

package cn.itcast.proxy.sh;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class ProxyTest {@Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("cn/itcast/proxy/sh/applicationContext-proxy.xml");PersonDao personDao = (PersonDao)context.getBean("personDao2");personDao.deletePerson();}
}

静态代理的缺点

静态代理模式的缺点:
1、如果一个系统中有100Dao,则创建100个代理对象
2、如果一个dao中有很多方法需要事务,则代理对象的方法中重复代码还是很多
3、由第一点和第二点可以得出:proxy的重用性不强

动态代理

1、产生的代理对象和目标对象实现了共同的接口
jdk动态代理
2、代理对象是目标对象的子类
hibernate: Person person = session.load(Person.class,1L); javassisit
spring:cglib动态代理

jdk的动态代理:
1、因为是用jdk的API做到的
2、代理对象是动态产生的
cglib产生的代理类是目标类的子类

注意事项:
1、拦截器中invoke方法体的内容就是代理对象方法体的内容
2、当客户端执行代理对象.方法时,进入到了拦截器的invoke方法体
3、拦截器中invoke方法的method参数是在调用的时候赋值的

jdk动态代理

定义一个接口

package cn.itcast.jdkproxy.sh;public interface PersonDao {public void savePerson();public void updatePerson();public void deletePerson();
}

目标类

package cn.itcast.jdkproxy.sh;public class PersonDaoImpl implements PersonDao{public void deletePerson() {System.out.println("delete person");}public void savePerson() {System.out.println("save person");}public void updatePerson() {System.out.println("update person");}
}

拦截器

package cn.itcast.jdkproxy.sh;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** 拦截器* @author Think*   1、引入目标类*   2、引入事务*   3、通过构造函数给目标类和事务赋值*   4、填充invoke方法**/
public class PersonInterceptor implements InvocationHandler{private Object target;//目标类private Transaction transaction;//引入事务public PersonInterceptor(Object target,Transaction transaction){this.target = target;this.transaction = transaction;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// TODO Auto-generated method stubthis.transaction.beginTransaction();method.invoke(this.target, args);//调用目标类的方法this.transaction.commit();return null;}}

使用

package cn.itcast.jdkproxy.sh;import java.lang.reflect.Proxy;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class ProxyTest {@Testpublic void test(){Object target = new PersonDaoImpl();Transaction transaction = new Transaction();PersonInterceptor interceptor = new PersonInterceptor(target, transaction);/*** 1、目标类的类加载器* 2、目标类实现的所有的接口* 3、拦截器*/PersonDao personDao = (PersonDao)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), interceptor);personDao.deletePerson();}
}

cglib动态代理

JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

目标类

package net.battier.dao.impl;  /** * 这个是没有实现接口的实现类 *  * @author student *  */  public class BookFacadeImpl1 {  public void addBook() {  System.out.println("增加图书的普通方法...");  }  }  

拦截类

package net.battier.proxy;  import java.lang.reflect.Method;  import net.sf.cglib.proxy.Enhancer;  
import net.sf.cglib.proxy.MethodInterceptor;  
import net.sf.cglib.proxy.MethodProxy;  /** * 使用cglib动态代理 *  * @author student *  */  public class BookFacadeCglib implements MethodInterceptor {  private Object target;  /** * 创建代理对象 *  * @param target * @return */  public Object getInstance(Object target) {  this.target = target;  Enhancer enhancer = new Enhancer();  enhancer.setSuperclass(this.target.getClass());  // 回调方法  enhancer.setCallback(this);  // 创建代理对象  return enhancer.create();  }  @Override  // 回调方法  public Object intercept(Object obj, Method method, Object[] args,  MethodProxy proxy) throws Throwable {  System.out.println("事物开始");  proxy.invokeSuper(obj, args);  System.out.println("事物结束");  return null;  }  }  

使用

package net.battier.test;  import net.battier.dao.impl.BookFacadeImpl1;  
import net.battier.proxy.BookFacadeCglib;  public class TestCglib {  public static void main(String[] args) {  BookFacadeCglib cglib=new BookFacadeCglib();  BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1());  bookCglib.addBook();  }  
}  

参考链接

java动态代理(JDK和cglib) - C’est la vie - 博客园

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/494196.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

lisp中的*,**,***

在lisp中“*”除了乘法的作用外,还被用来保存REPL(read-eval-print-loop)中的返回值。其中 * -> 保存最后一次返回值。 ** -> *的上一次值。 *** -> **的上一次值。 例子如下: 而且  * (car /) ** …

《Python 快速入门》一千个程序员有一千套编码规范

一千个读者有一千个哈姆莱特。 -- 莎士比亚 一千个程序员有一千套编码规范。 -- 不吃西红柿 目录 1、分号 2、命名 3、行长度 4、缩进 5、空行 6、空格 7、类 8、块注释和行注释 9、字符串 10、导包 【总结】 1.命名 2.空白 3.语句 4.注释 Python 编码…

为了帮粉丝完成毕业设计,我发现了一款私活神器

一、缘起 不日前,有粉丝找到我,让我帮着做个: 教师管理系统 由于种种借口,我当时把问题交给群友去解决了..... 思来想去,越想越内疚,于是就请教了经常做私活的小伙伴。 必须分享给更多的小伙伴~ 二、揭开面…

狗脸识别APP整合

本文主要包括以下内容 android studio中导入so文件 通过URI获得Bitmap android studio中导入so文件 在main文件夹下建立jniLibs目录,并将so文件拷贝进去即可。 注意 声明的native方法与so文件中定义的方法的包名必须相同 通过URI获得Bitmap private Bitmap …

解析丰田对自动驾驶汽车的愿景:打造更加安全的汽车

丰田高管约翰莱昂纳德在丰田研究所的麻省理工学院车库,在他身后是研究所改造的一辆雷克萨斯选自:Bloomberg来源: 网易科技参与:乐邦约翰莱昂纳德(John Leonard)漫步走到麻省理工学院(MIT)校园里一间单调乏味的一层车库&#xff0c…

C#用IrisSkin4.dll 美化Winform窗体

前期准备: 1、IrisSkin4.dll2、Skin文件,后缀名为.ssk3、一个WinForm程序 直接拷贝IrisSkin4.dll文件到系统目录里:1、Windows 95/98/Me系统,将dll复制到C:\Windows\System目录下。2、Windows NT/2000系统,将dll复制到…

luogu题目精讲(C++):【入门1】顺序结构(1~5题)

B2002 Hello,World! # Hello,World! ## 题目描述 编写一个能够输出 Hello,World! 的程序。 提示: - 使用英文标点符号; - Hello,World! 逗号后面**没有**空格。 - H 和 W 为**大写**字母。 ## 输入格式 ## 输出格式 ## 样例 #1 ### 样例输入 #1 …

C站最全Python库总结丨标准库+高级库

梦想还是要有的,万一别人问呢? 作者:不吃西红柿 简介:CSDN博客专家、蓝桥签约作者、大数据&Python领域优质创作者。 CSDN私信我,回复【资料】领取: 1、100套小编购买的简历模板; 2、1000套…

postgresql命令

转自:http://blog.sina.com.cn/s/blog_4b93170a01000b2i.html1.PostgresSQL 支持标准的 SQL 类型 int,smallint, real,double precision, char(N), varchar(N),date, time&#xff0…

DeepMind-深度学习: AI革命及其前沿进展 (54页ppt报告)

来源:专知摘要:2018年9 月 9 日-14 日,DeepMind主办的Deep Learning Indaba 2018 大会在南非斯泰伦博斯举行。会上,牛津大学教授和其他15位专家做了《深度学习: AI革命及其前沿进展》的报告。Nando de FreitasNando de Freitas是一…

❤️ 6个Python办公黑科技,工作效率提升100倍!HR小姐姐都馋哭了(附代码)❤️

🍅 作者:不吃西红柿 🍅 简介:CSDN博客专家🏆、信息技术智库公号作者✌。简历模板、职场PPT模板、技术难题交流、面试套路尽管【关注】私聊我。 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 如有…

Spring之数据库操作

本文主要包括以下内容 springjdbc数据库操作 springjdbc声明事务处理 springhibernate声明事务处理 springjdbc数据库操作 方法 1、让自己写的一个dao类继承JdbcDaoSupport 2、让自己写的一个dao类继承JdbcTemplate 3、让自己写的一个dao类里有一个属性为JdbcTemplate …

iOS网络编程-ASIHTTPRequest框架同步请求

在ASIHTTPRequest框架中与HTTP请求相关的类有:ASIHTTPRequest和ASIFormDataRequest,其中最常用的是ASIHTTPRequest,ASIFormDataRequest是ASIHTTPRequest的子类,ASIFormDataRequest可以发送类似与HTML表单数据,也可以上…

苹果未来秘密在这里!从神秘组织到七大技术布局

来源:智东西随着人工智能的艰难发展,智能手机增长的放缓, 苹果公司能否第三次重塑自我?在很多方面,苹果仍然是一家以Steve Jobs个人形象制造的公司,专注于颠覆性产品。但今天,苹果走在了十字路口…

❤️ 爬虫分析CSDN大佬之间关系,堪比娱乐圈 ❤️

🍅 作者主页:不吃西红柿 🍅 简介:CSDN博客专家🏆、信息技术智库公号作者✌简历模板、PPT模板、技术资料尽管【关注】私聊我。历史文章目录:https://t.1yb.co/zHJo 🍅 欢迎点赞 👍 …

编程之美--读书笔记--返回一个数组中所有元素被第一个元素除的结果

笔试题目1:写一个函数,返回一个数组中所有元素被第一个元素除的结果 很多人会想到如下: void DivAarry(int *pArray,int size) { for(int isize-1;i>0;i--) { pArray[i] / pArray[0]; } } 问题1:可不可以把循环正着…

SSH框架整合

ssh框架整合步骤如下 提示:myeclipse环境、工程环境、tomcat环境的jdk保持一致 1、新建一个工程,把工程的编码为utf-8 2、把jsp的编码形式改成utf-8 3、把jar包放入到lib下 4、建立三个src folder src 存放源代码 config 存放配置文件 hibernate…

给你的Linux把把脉(内存、磁盘、CPU、网络)

🍅 作者主页:不吃西红柿 🍅 简介:CSDN博客专家🏆、信息技术智库公号作者✌。简历模板、职场PPT模板、技术难题交流、面试套路尽管【关注】私聊我。 今日重点: ① 学会查看linux各种状态,包括:网络IO、磁盘、CPU、内存等; ② 学会理解命令所代表的含义,能够…

关于未来的10点核心思考

作者:尤瓦尔赫拉利 牛津大学历史学博士,全球瞩目的新锐历史学家来源:《今日简史》世界正在变得越来越复杂,我们正在陷入知识的错觉和群体的无知。同时,我们的生活被社交媒体所塑造,真相早已不存在&#xff…

❤️爆肝3万字,最硬核丨Mysql 知识体系、命令全集 【建议收藏 】❤️

🍅 作者主页:不吃西红柿 🍅 简介:CSDN博客专家🏆、信息技术智库公号作者✌ 简历模板、PPT模板、学习资料、面试题库、技术互助【关注我,都给你】 🍅 欢迎点赞 👍 收藏 ⭐留言 &am…