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的动态代理,然后就有了这篇文章 ...
随机推荐
- idea创建maven项目需要注意的问题
idea创建maven项目之后,我从deployment中看到报部署错误的问题,下图是解决问题的办法如下图所示:
- navicat for mysql 2003错误
最近又一次碰到navicat for mysql 2003错误,之前碰到好几次了,问题再次出现还是有些不知所措,所以记下来,再次遇到时就可以迎韧有余了. 解决方案1: 重启防火墙:关闭再重新开启. 解 ...
- 洛谷P3120 [USACO15FEB]Cow Hopscotch
题目描述 Just like humans enjoy playing the game of Hopscotch, Farmer John's cows have invented ...
- 【ZOJ4070】Function and Function(签到)
题意:求 k 层嵌套的 f(x) 0<=x,k<=1e9 思路:迭代不会很多次后函数里就会=0或者1,再看层数奇偶直接返回答案 #include<cstdio> #includ ...
- Android 画笔Paint
转自 http://wuxiaolong.me/2016/08/20/Paint/ 了解Android Paint,一篇就够.引用Aige<自定义控件其实很简单>系列博客的话“很多时候你压 ...
- C++中的 Round(),floor(),ceil()
2.1 2.6 -2.1 -2.6floor : 不大于自变量的最大整数 2 ...
- [LeetCode] Evaluate Reverse Polish Notation stack 栈
Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...
- 【原创】Linux环境下的图形系统和AMD R600显卡编程(10)——R600显卡的3D引擎编程
3D图形处理流水线需要流经多个硬件单元才能得到最后的渲染结果,流水线上的所有的硬件单元必须被正确编程,才能得到正确的结果. 总体上看,从图形处理流水线的源头开始,需要准备好vertex和index,在 ...
- 使用vim进行java编程
首先:编写源代码Test.java 1class Test{ ...
- Linux SPI总线和设备驱动架构之一:系统概述【转】
转自:http://blog.csdn.net/droidphone/article/details/23367051/ 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 硬 ...