Java动态代理 cglib
代理模式:为某些对象提供代理以实现对这个对象的访问。
对一个对象进行访问控制的原因是为了只有在我们确实需要这个对象时才对它进行创建和初始化。
一般包括以下组件:
被代理者接口:提供被代理者的访问途径。
被代理者:定义真实对象。
代理者:保存一个被代理者的引用, 并对外提供统一的代理方法, 可以对被代理者的方法实现修饰和控制。
要生成某一个对象的代理对象,这个代理对象通常也要编写一个类来生成,所以首先要编写用于生成代理对象的类。java在JDK1.5之后提供了java.lang.reflect.Proxy类,通过Proxy类提供的newProxyInstance方法用来创建一个对象的代理对象,这个方法总共有3个参数,ClassLoader loader用来指明生成代理对象使用哪个类装载器,Class<?>[] interfaces用来指明生成哪个对象的代理对象,通过接口指定,InvocationHandler 用来指明产生的这个代理对象要做什么事情。所以只需要调用newProxyInstance方法就可以得到某一个对象的代理对象了。
代理类需要实现InvocationHandler接口,该接口只有一个invoke方法,用于自定义代理行为.
JDK动态代理示例
----------------
//代理接口
public interface IClient {
void doSomething(String thing);
}
-
//被代理者
public class Client implements IClient {
@Override
public void doSomething(String thing) {
System.out.println("do a thing:" + thing);
}
}
-
//代理
public class ProxyAgent implements InvocationHandler {
private Object client; public ProxyAgent(Object client) {
this.client = client;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 这里可以对method进行过滤或添加其他代码,然后调具体对象的方法
Object object = method.invoke(client, args);
return object;
} //获取代理实例
public Object getProxy(){
return Proxy.newProxyInstance(getClass().getClassLoader(), client.getClass().getInterfaces(), this);
} public static void main(String[] args){
//被代理者
Client client = new Client();
//代理者
IClient proxy = (IClient) new ProxyAgent(client).getProxy();
//调用代理动作
proxy.doSomething("buy something");
}
}
----------------
由上可见,使用JDK的Proxy实现动态代理有一个要求:被代理的类必须实现接口,未实现接口则没办法完成动态代理。
实际中有些类没有实现接口,不应该为了实现动态代理而去抽出一些没有实例意义的接口,可以通过cglib对一个类实现代理。
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.4</version>
</dependency>
示例如下:
package cn.luan.demo; 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 DynamicProxy implements MethodInterceptor { // 被代理对象
Object targetObject; // 动态生成一个新的类,使用父类的无参构造方法创建一个指定了特定回调的代理实例
public Object getProxyObject(Object object) {
//set被代理对象
this.targetObject = object;
//动态代码生成器
Enhancer enhancer=new Enhancer();
//回调方法
enhancer.setCallback(this);
//设置生成类的父类类型
enhancer.setSuperclass(targetObject.getClass());
//动态生成字节码并返回代理对象
return enhancer.create();
} // 实现了一个方法拦截器接口
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("方法调用前织入的横切内容");
System.out.println("method name: " + method.getName()); // 调用方法
Object result = methodProxy.invoke(targetObject, args); System.out.println("方法调用后织入的横切内容"); return result;
} //测试
public static void main(String[] args) {
Client client = (Client) new DynamicProxy().getProxyObject(new Client());
client.doSomething("cglib proxy");
}
}
--cglib不能对final类做代理
end
Java动态代理 cglib的更多相关文章
- Java动态代理--CGLib实现
上一篇说了通过JDK实现实现了动态代理,但是用JDK实现代理,要求所代理的类必须实现一个接口.如果我们类不实现接口,这就在无法使用JDK提供的Proxy来实现动态代理,这个时候我们应该怎么办呢?我们找 ...
- [转]java动态代理(JDK和cglib)
转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理 ...
- Java静态代理&动态代理&Cglib代理详解
一.静态代理 根据被代理的类的时机的不同,如果在编译阶段就能确定下来的被代理的类是哪一个,那么,就可以使用静态代理的方式. 申明一个接口: /** * @author jiaqing.xu@hand- ...
- CGLIB和Java动态代理的区别(笔记)
java常用知识点: 1.Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承):CGLIB能够代理普通类:2.Jav ...
- Java动态代理与CGLib
Java帝国之动态代理 CGLib:从兄弟到父子-动态代理在民间是怎么玩的? 以上两篇文章引用自微信公众号: 码农翻身 Java动态代理 深度详解 以上文章引用博客园:陈树义
- Java动态代理(三)——Cglib动态代理
一.Cglib动态代理Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用Cglib即使代理类没有实现任何接口也可以实现动态代理功能.而且,它的运行速度要远远快 ...
- java动态代理(JDK和CGLIB)笔记
动态代理:为一堆interface或类的实现提供统一的执行通道,从含义上就像局域网电脑通过代理上网一样,走统一的通道,代理控制通道,自然可以在通道里加上自定义实现,例如像AOP切面,日志等. JDK的 ...
- Java动态代理全面分析
代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1 主题:规定代理类和真实对象共同对外暴露的接口: 2 代理类:专门代理真实对象的类: 3 ...
- Java 动态代理作用是什么?
Java 动态代理作用是什么? 1 条评论 分享 默认排序按时间排序 19 个回答 133赞同反对,不会显示你的姓名 Intopass 程序员,近期沉迷于动漫ING 133 人赞同 ① 首先你 ...
随机推荐
- linux第1天 fork exec 守护进程
概念方面 文件是对I/O设备的抽象表示.虚拟存储器是对主存和磁盘I/O设备的抽象表示.进程则是对处理器.主存和I/O设备的抽象表示 中断 早期是没有进程这个概念,当出现中断技术以后才出现进程这个概念 ...
- Java实现找出数组中重复次数最多的元素以及个数
/**数组中元素重复最多的数 * @param array * @author shaobn * @param array */ public static void getMethod_4(int[ ...
- sql server output用法说明
带有output的insert语句. @@identity只能返回当前会话最后生产的标识列. 如果一次性插入多条语句的话. 需要返回这些自动生产的标识列. 那么outpu就派上用场了. declar ...
- Junit单元测试-环境配置
JUnit是Java单元测试框架,已经在Eclipse中默认安装.目前主流的有JUnit3和JUnit4.JUnit3中,测试用例需要继承TestCase类.JUnit4中,测试用例无需继承TestC ...
- full_case & parallel_case
case中的full_case与parallel_case讨论: 1)术语介绍: 整个case模块叫做:case_statement,注释部分叫做case_statement_header case ...
- PAT乙级 1015. 德才论 (25)
1015. 德才论 (25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Li 宋代史学家司马光在<资治通鉴&g ...
- 手机端js事件支持(event)
http://blog.163.com/rex_blog/blog/static/1944801012013102743014369/ 所有被测试的浏览器都支持touchstart.touchend和 ...
- 转:MyEclipse8.6插件安装方法
通常,我们可以用update来直接安装.但是myeclipse限制了中国区的下载和更新.所以我们只能用插件配置的方法来实现. MyEclipse8.6插件安装同Eclipse插件安装方式大致相同,如下 ...
- rotate array 旋转数组
class Solution {public: void rotate(vector<int>& nums, int k) { int n=nums.size(); int i=0 ...
- nexus启动不了
nexus一分钟前还能正常启动,突然就启动不了,看了下启动文件,变成0KB就知道什么问题了,文件被系统洗了. 解决方案:重新解压缩文件包里复制一个过来.