2017.5.1 java动态代理总结
参考来自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html
1.代理模式
代理类和委托类有相同接口。
代理类负责为委托类:预处理消息
过滤消息
把消息转发给委托类
事后处理消息等
代理类和委托类会相关联。
代理类不真正实现服务,而是通过调用委托类的相关方法,来提供服务。
2.代理的分类
静态代理:由程序员创建,或者由特定工具自动生成源代码,再对其编译。在运行之前,代理类的.class文件就存在了。
动态代理:在程序运行时,根据java的反射机制动态创建。
3 jdk动态代理:委托类必须实现接口。
4 Cglib动态代理:委托类不用实现接口,针对类。
2.1 静态代理
(1)实例
public interface Count {
// 查看账户方法
public void queryCount();
// 修改账户方法
public void updateCount();
}
public class CountImpl implements Count { @Override
public void queryCount() {
System.out.println("查看账户方法...");
} @Override
public void updateCount() {
System.out.println("修改账户方法...");
}
}
创建一个代理类,可以看到CountProxy和CountImpl实现了同样的接口:Count。
public class CountProxy implements Count {
private CountImpl countImpl; /**
* 覆盖默认构造器
*
* @param countImpl
*/
public CountProxy(CountImpl countImpl) {
this.countImpl = countImpl;
} @Override
public void queryCount() {
System.out.println("事务处理之前");
// 调用委托类的方法;
countImpl.queryCount();
System.out.println("事务处理之后");
} @Override
public void updateCount() {
System.out.println("事务处理之前");
// 调用委托类的方法;
countImpl.updateCount();
System.out.println("事务处理之后");
} }
(2)测试
由测试可知,采用constructor关联起来的proxy和impl,必须是1对1的,十分低效。
public class TestCount {
public static void main(String[] args) {
CountImpl countImpl = new CountImpl();
CountProxy countProxy = new CountProxy(countImpl);
countProxy.updateCount();
countProxy.queryCount();
}
}
显然,通过上面的代码可以知道,这样的代理类只能为一个接口服务,会产生过多的代理类。而且所有的代理类中除了调用的方法不一样,其他操作都一样,重复代码过多。为了使用一个代理类来完成全部的代理功能,显然不能在运行前就生成好代理类的.class文件。即,必须使用动态代理。
2.2 JDK动态代理
(1)interface InvocationHandler
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
参数说明:
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数
(2)class Proxy
java.lang.reflect.Proxy类提供了一个方法:newProxyInstance。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
参数说明:
1 ClassLoader loader:类加载器
2 Class<?>[] interfaces:得到全部的接口
3 InvocationHandler h:得到InvocationHandler接口的子类实例
(3)实例
1 public interface BookFacade {
2 public void addBook();
3 }
4
5 public class BookFacadeImpl implements BookFacade {
6
7 @Override
8 public void addBook() {
9 System.out.println("增加图书方法。。。");
10 }
11 }
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class BookFacadeProxy implements InvocationHandler {
private Object target;
/**
* 绑定委托对象并返回一个代理类
* @param target 委托对象
* @return 代理类
*/
public Object bind(Object target) {
this.target = target;
//取得代理对象 //要绑定接口(这是一个缺陷,cglib弥补了)
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
16 target.getClass().getInterfaces(),
17 this);
} @Override
/**
* 调用委托类的方法
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=null;
System.out.println("事物开始");
//执行方法
result=method.invoke(target, args);
System.out.println("事物结束");
return result;
}
}
(4)测试
由测试可知,此时只需要一个代理类,就可以通用了。但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。
public class TestProxy { public static void main(String[] args) {
BookFacadeProxy proxy = new BookFacadeProxy();
BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());
bookProxy.addBook();
}
}
2.3 Cglib动态代理
由前面可知,当委托类并没有实现某个接口(implements someInterface)时,jdk动态代理就不能使用了。
cglib是针对类来实现代理(没有实现某个接口也不会造成影响),原理:对委托类生成一个子类(局限:final),并覆盖其中方法实现增强。
(1)实例
public class BookFacadeImpl1 { //没有implements BookFacade
public void addBook() {
System.out.println("增加图书的普通方法...");
}
}
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; 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;
}
}
(2)测试
public class TestCglib { public static void main(String[] args) {
BookFacadeCglib cglib=new BookFacadeCglib();
BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1());
bookCglib.addBook();
}
}
3.总结
静态代理缺点:代码一对一,重复冗余,编译时就需要存在代理类的.class文件。
动态代理优点:动态生成,统一处理,运行时生成代理类。
jdk动态代理: Proxy,InvocationHandler
cglib动态代理:MethodInterceptor
2017.5.1 java动态代理总结的更多相关文章
- java动态代理实现与原理详细分析
关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式 代理模式是常用的java设计模式, ...
- java动态代理实现与原理详细分析(转)
关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式 代理模式是常用的java设计模式, ...
- Java 动态代理机制详解
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- Java动态代理全面分析
代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1 主题:规定代理类和真实对象共同对外暴露的接口: 2 代理类:专门代理真实对象的类: 3 ...
- JAVA动态代理模式(从现实生活角度理解代码原理)
所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...
- Java 动态代理作用是什么?
Java 动态代理作用是什么? 1 条评论 分享 默认排序按时间排序 19 个回答 133赞同反对,不会显示你的姓名 Intopass 程序员,近期沉迷于动漫ING 133 人赞同 ① 首先你 ...
- java动态代理原理
我们经常会用到Java的动态代理技术, 虽然会使用, 但是自己对其中的原理却不是很了解.比如代理对象是如何产生的, InvocationHandler的invoke方法是如何调用的?今天就来深究下Ja ...
- java 动态代理示例,带主要注释
Java proxy是基于反射,仅仅支持基于接口的动态代理. java 动态代理是一切架构的基础,必须了解. 废话少说,先上代码获得感性认识. 示例代码有主要注释. 接口: public interf ...
- java动态代理浅析
最近在公司看到了mybatis与spring整合中MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类. 于是想起了java的动态代理,然后就有了这篇文章 ...
随机推荐
- 刷题总结——子串(NOIP2015)
题目: 题目背景 NOIP2015 提高组 Day2 T2 题目描述 有两个仅包含小写英文字母的字符串 A 和 B .现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在 ...
- SQL 设置自增,和default
mysql数据库为表中已有的主键字段增加自增属性: ALTER TABLE `category ` MODIFY COLUMN `id` int(11) NOT NULL AUTO_INCREMENT ...
- UVa10891 Game of Sum
给定n个数字,A和B可以从这串数字的两端任意选数字,一次只能从一端选取.两人都采用最优策略,A先手,问A和B各自得到数字的和的差值最大为多少? 区间DP F[i][j]表示区间i~j内A能得到的最大数 ...
- 仿Orm 自动生成分页SQL
分页的写法 自从用上了Orm,分页这种事就是腰不酸腿不痛了.不过有时候想用纯粹的ado.net来操作,希望返回的数据是原生的DataTable或DbDataReader类似的东西,故研究下怎么生成分页 ...
- IAT Hook
@author: dlive 0X01 IAT Hook的优缺点 优点:工作原理与实现都比较简单 缺点:如果想钩取的API不在目标进程的IAT中,那么就无法使用该技术进行钩取操作.即如果要钩取的API ...
- Codeforces #105 DIV2 ABCDE
开始按照顺序刷刷以前的CF. #include <map> #include <set> #include <list> #include <cmath> ...
- Kubernetes镜像制作
#将需要安装的包全部放入一个目录下,然后开始编写Dockerfile#Dockerfile格式FROM #依赖的镜像MAINTAINER #制作者信息WORKDIR #工作目录,打包启动镜像后的所在目 ...
- 开发API完成,写个文档
Jira对接Prism开发API指南 部门 证系统运维团队 文档制作人 陈刚() 时间 2017-04-05 版本 第一版 目录 目的... 1 通例:... 1 认证... 2 新建版本单... 2 ...
- HDU 2546.饭卡-动态规划0-1背包
饭卡 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submissi ...
- Codeforces 1010D Mars rover
题目大意:对于一个不完全二分图,根节点为1,叶节点值为0或1,非叶节点包含一个操作(and,or,xor,not),求改变各个叶节点的值时(即0改为1,1改为0),根节点的值是多少 解法:遍历图求各节 ...