java设计模式(一)动态代理模式,JDK与CGLIB分析
-本想着这个知识点放到Spring Aop说说可能更合适一点,但因为上一篇有所提到就简单分析下,不足之处请多多评论留言,相互学习,有所提高才是关键!
什么是代理模式:
记得有本24种设计模式的书讲到代理模式的经典例子,说的是西门庆、王婆、潘金莲的故事,比如西门庆找潘金莲,不好意思啊,则么办,找那个王婆做代理, 代理模式就是找个东西代替自己完成自己的活,这个就称之为代理。如宋哲经纪人,找房子中介......具体看看代码怎么写
区别
- JDK动态代理只能对实现了接口的类生成代理,而不能针对类
- CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)
--JDK动态代理
- 定义一个接口,保存和修改方法
public interface UserDao {
 public void save();
 public void update(); }public class UserDaoImpl implements UserDao { @Override
 public void save() {
 System.out.println("sava doing .........");
 }
 @Override
 public void update() {
 System.out.println("update doing .........");
 } }
- 测试一把:
public class TestProxy {
 @Test
 public void run1(){
 //创建对象方式调用方法执行。
 UserDao dao = new UserDaoImpl();
 dao.save();
 dao.update(); System.out.println("============================="); }
 }
 sava doing .........
 update doing .........
 =============================
- 加入代理模式   java.lang.reflect.Proxy   import java.lang.reflect.InvocationHandler; 
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy; import com.kk.Dao.UserDao;
 /**
 * 使用JDK的方式生成代理对象
 * @author Administrator
 */
 public class MyProxyUtils { public static UserDao getProxy(final UserDao dao) {
 // 使用Proxy类生成代理对象
 UserDao proxy = (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(),
 dao.getClass().getInterfaces(), new InvocationHandler() { // 代理对象方法一直线,invoke方法就会执行一次
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 //在此可以利用代理对象来增强方法 比如在执行方法前记录一条日志。 当然进行权限校验,日志记录,性能监控,事务控制等都可以在此加强。这也是aop思想
 if("save".equals(method.getName())){
 System.out.println("记录日志...");
 }
 //让dao类的save或者update方法正常的执行下去
 UserDao invoke =(UserDao) method.invoke(dao, args);
 return invoke;
 }
 });
 // 返回代理对象
 return proxy;
 } }
- 测试第二把:利用代理对象测试
public class TestProxy {
 @Test
 public void run1(){
 UserDao dao = new UserDaoImpl();
 // 使用工具类,获取到代理对象
 UserDao proxy = MyProxyUtils.getProxy(dao);
 // 通过代理对象调用方法
 proxy.save();
 proxy.update();
 }
 }
 记录日志...
 sava doing .........
 update doing .........
由此可以看出来,在我方法执行前,我在没有改变原方法前加了一段记录日志/代码,这就是一种aop思想,降低代码耦合度。
CGLIB代理方式:
- 加入cglib-2.2.2.jar: 及三方依赖  asm-3.3.1.jar
 
- 编写BookDaoImpl实现类 - public class BookDaoImpl {
 public void save() {
 System.out.println("sava doing .........");
 }
 public void update() {
 System.out.println("update doing .........");
 }
 }
- CGLIB创建代理方式工具类
package com.kk.Utils; 
 import java.lang.reflect.Method; import com.kk.DaoImpl.BookDaoImpl;
 import com.kk.DaoImpl.UserDaoImpl; import net.sf.cglib.proxy.Enhancer;
 import net.sf.cglib.proxy.MethodInterceptor;
 import net.sf.cglib.proxy.MethodProxy; public class MyCglibUtils { /**
 * 使用CGLIB方式生成代理的对象
 *
 * @return
 */
 public static BookDaoImpl getProxy( BookDaoImpl bookDaoImpl) {
 Enhancer enhancer = new Enhancer();
 // 设置父类
 enhancer.setSuperclass(bookDaoImpl.getClass());
 // 设置回调函数
 enhancer.setCallback(new MethodInterceptor() {
 // 代理对象的方法执行,回调函数就会执行
 public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
 if(method.getName().equals("save")){
 System.out.println("记录日志...");
 }
 // 正常执行
 return methodProxy.invokeSuper(obj, args);
 }
 });
 // 生成代理对象
 BookDaoImpl proxy = (BookDaoImpl) enhancer.create();
 return proxy;
 }
 }
- 测试一把:
@Test 
 public void run1(){
 //目标对象
 BookDaoImpl dao = new BookDaoImpl();
 // 通过代理对象调用方法
 dao.save();
 dao.update();
 System.out.println("================================");
 BookDaoImpl proxy = MyCglibUtils.getProxy(dao);
 proxy.save();
 proxy.update();
 } sava doing .........
 update doing .........
 ================================
 记录日志...
 sava doing .........
 update doing .........同理:通过代理对象可以帮我们完成代码增强等功能,注意:JDK代理是通过接口模式,而CGLIB则通过实现类方式帮我们创建代理对象。后期Spring会更深了解。Spring在选择用JDK还是CGLiB的依据:
- 当Bean实现接口时,Spring就会用JDK的动态代理
- 当Bean没有实现接口时,Spring使用CGlib是实现
- 可以强制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)
CGlib比JDK快?
- 使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。
- 在对JDK动态代理与CGlib动态代理的代码实验中看,1W次执行下,JDK7及8的动态代理性能比CGlib要好20%左右。
java设计模式(一)动态代理模式,JDK与CGLIB分析的更多相关文章
- Java中的动态代理(jdk和cglib)
		JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类 ... 
- Java设计模式—Proxy动态代理模式
		代理:设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 图 1. 代 ... 
- 代理设计模式 (静态代理设计模式)+  动态代理(JDK和Cglib)
		一.代理设计模式 1.设计模式:前人总结一套解决特定问题的代码 2.代理设计模式优点: 2.1 保护真实对象 2.2 让真实对象职责更明确 2.3 扩展 3.代理设计模式 3.1 真实对象(老总) 3 ... 
- [转]java动态代理(JDK和cglib)
		转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理 ... 
- java设计模式之Proxy(代理模式)
		java设计模式之Proxy(代理模式) 2008-03-25 20:30 227人阅读 评论(0) 收藏 举报 设计模式javaauthorizationpermissionsstringclass ... 
- Java设计模式之《代理模式》及应用场景
		原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6525527.html 代理模式算是我接触较早的模式,代理就是中介,中间人.法律上也有代理, ... 
- Java的三种代理模式&完整源码分析
		Java的三种代理模式&完整源码分析 参考资料: 博客园-Java的三种代理模式 简书-JDK动态代理-超详细源码分析 [博客园-WeakCache缓存的实现机制](https://www.c ... 
- Java 的静态代理 动态代理(JDK和cglib)
		转载:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是 ... 
- java的静态代理和动态代理(jdk、cglib)
		一.代理模式 代理的概念来自于设计模式中的代理模式,先了解一下代理模式 1.结构图 2.参与者 Subject:接口,定义代理类和实际类的共用接口 RealSubject:实际类,实现Subject这 ... 
- java动态代理(JDK和cglib)
		转:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代 ... 
随机推荐
- 【集合系列】- 深入浅出的分析IdentityHashMap
			一.摘要 在集合系列的第一章,咱们了解到,Map 的实现类有 HashMap.LinkedHashMap.TreeMap.IdentityHashMap.WeakHashMap.Hashtable.P ... 
- (四十)golang--单元测试
			传统的测试: package main import ( "fmt" ) func addUpper(n int) int { res := ; i <= n; i++ { ... 
- Linux考题(一)
			1.创建目录/data/oldboy,并且在该目录下创建oldboy.txt,然后在文件oldybos.txt里写入内容“inet addr:192.168.228.128 Bcast:192.16 ... 
- DexOpt相关的异常
			查找的资料 dvm探讨之odex绕过 DexClassLoader4.4.2动态加载分析(磁盘加载分析) - ::): DexOpt: incorrect opt magic number (0xff ... 
- Rust 入门 (二)
			我认为学习计算机语言,应该先用后学,这一节,我们来实现一个猜数字的小游戏. 先简单介绍一个这个游戏的内容:游戏先生成一个1到100之间的任意一个数字,然后我们输入自己猜测的数字,游戏会告诉我们输入的数 ... 
- 在Spring Security框架下JWT的实现细节原理
			一.回顾JWT的授权及鉴权流程 在笔者的上一篇文章中,已经为大家介绍了JWT以及其结构及使用方法.其授权与鉴权流程浓缩为以下两句话 授权:使用可信用户信息(用户名密码.短信登录)换取带有签名的JWT令 ... 
- Xtrabackup 增量备份 和 增量还原
			目录 测试数据准备 进行全量备份 第一次增量插入一条数据 进行第一次增量备份 注意 第二次增量插入一条数据 进行第二次增量备份 注意 查看xtrabackup_binlog_info中的binlog位 ... 
- X86架构CPU常识(主频,外频,FSB,cpu位和字长,倍频系数,缓存,CPU扩展指令集,CPU内核和I/O工作电压,制造工艺,指令集,超流水线与超标量)
			1.主频 主频也叫时钟频率,单位是MHz,用来表示CPU的运算速度. CPU的主频=外频×倍频系数.很多人认为主频就决定着CPU的运行速度,这不仅是个片面的,而且对于服务器来讲,这个认识也出现了偏差. ... 
- Linux发展历史(简略)
			LINUX UNIX历史发展 1969肯 汤姆森在DEC PDP-7机器上开发出了UNIX系统 1971肯 汤姆森的同事丹尼斯 里奇发明了C语言 1973UNIX系统绝大部分用C语言重写,为提高UNI ... 
- mysql那些事(2)时间类型数据如何存储
			几乎每次数据库建模的时候,都会遇到时间类型数据存储的问题. mysql存储时间通常选择这四种类型:datetime.timestamp.int和bigint四种方式,到底使用什么类型,需要看具体的业务 ... 
