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 人赞同 ① 首先你 ...
随机推荐
- node.js http.get 和http.post 数据
http.get('http://codestudy.sinaapp.com', function (response) {}); node.js http post 样例: var reqData= ...
- spark history-server的使用
为什么需要historyServer? 在运行Spark Application的时候,Spark会提供一个WEBUI列出应用程序的运行时信息:但该WEBUI随着Application的完成(成功/失 ...
- Linux mysql 主从复制
主:192.168.246.130 从:192.168.246.131 主配制:my.conf server_id log-bin=mysql-bin binlog-format=mixed 从配制: ...
- 关于更改MYECLIPSE JS 代码背景颜色
白色的背景,看花了眼,你想改一下编辑器的背景颜色,移步这里就可以了. 这时你高兴的打开编辑器,发现颜色确实变了,但是当你打开有JS的JSP时,你碉堡了,发现JS的背景颜色还是默认的, 看着让人纠结,好 ...
- PHP人民币金额数字转中文大写的函数
<?php header("Content-Type:text/html;charset=utf-8"); error_reporting(2); function cny( ...
- Spring MVC 和 Spring 总结
1. 为什么使用Spring ? 1). 方便解耦,简化开发 通过Spring提供的IoC容器,可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合. 2). AOP编程的 ...
- Mac Book 上安装Windows 8 / 10 以后安装 Hyper-v 无法正常使用问题---虚拟化已禁止问题
Mac book由于工作需要装了双启动,平时工作用 Windows 10, 由于有些老程序无法启动,还得再装一个虚拟机. 起初装 WMWare 开始装 7.1版本,结果没安装完就直接崩溃重启, 网上反 ...
- 69道Java Spring 面试&笔试题
目录 Spring 概述 依赖注入 Spring beans Spring注解 Spring数据访问 Spring面向切面编程(AOP) Spring MVC Spring 概述 1. 什么是spri ...
- 有趣的insert死锁
昨天看到一个很有意思的死锁,拿来记录下: 环境:deadlock on 事务隔离级别: read commited 表结构: root::>show create table lingluo\G ...
- 161012、JAVA读写文件,如何避免中文乱码
1.JAVA读取文件,避免中文乱码. /** * 读取文件内容 * * @param filePathAndName * String 如 c:\\1.txt 绝对路径 * @return boole ...