java动态代理(JDK和CGLIB)笔记
动态代理:为一堆interface或类的实现提供统一的执行通道,从含义上就像局域网电脑通过代理上网一样,走统一的通道,代理控制通道,自然可以在通道里加上自定义实现,例如像AOP切面,日志等。
JDK的动态代理只能对接口实现,代理类需要实现InvocationHandler 接口。
一、接口
public interface UserService {
User addUser();
void editUser(User user);
int deleteUser(int userId);
}
//假设有这么一个User类
public class User {
private Integer userId;
private String userName;
private String password;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
'}';
}
}
二、接口的实现
public class UserServiceImpl implements UserService {
@Override
public User addUser() {
User user = new User();
user.setUserId(1);
user.setUserName("userTest");
user.setPassword("123456");
System.out.println("------> add user");
return user;
}
@Override
public void editUser(User user) {
System.out.println("------> edit user:" +user);
}
@Override
public int deleteUser(int userId) {
System.out.println("------> delete user:"+userId);
return 1;
}
}
三、JDK代理类实现InvocationHandler
public class ProxyHandler implements InvocationHandler {
//被代理对象
private Object proxied;
public ProxyHandler(Object proxied) {
this.proxied = proxied;
}
private void beforeInvoke(String msg)
{
System.out.println("-------> beforInvoke:"+msg);
}
private void afterInvoke(String msg)
{
System.out.println("-------> afterInvoke:"+msg);
}
private String convertArgs(Object[] args)
{
if(args==null || args.length==0)
{
return null;
}
StringBuilder sb= new StringBuilder();
for(Object object : args)
{
sb.append(object.toString());
}
return sb.toString();
}
//proxy是代理对象,可以想象成代理服务器
//proxied是被代理对象,可以想象成局域网里的PC
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforeInvoke("proxy name:"+proxy.getClass().getName());
beforeInvoke("proxied name:"+proxied.getClass().getName());
beforeInvoke( "args:"+convertArgs(args));
Object o = method.invoke(proxied,args);
afterInvoke("result:"+o);
return o;
}
}
四、使用,实现原理是反射
public class Main {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService proxyUserService = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class},
new ProxyHandler(userService)
);
User user = proxyUserService.addUser();
proxyUserService.editUser(user);
proxyUserService.deleteUser(user.getUserId());
}
}
五、结果:符合预期的输出

六、简化一下写法,代理类的生成方式
public class DynamicProxy implements InvocationHandler {
private Object proxied;
private void beforeInvoke(String msg)
{
System.out.println("-------> beforInvoke:"+msg);
}
private void afterInvoke(String msg)
{
System.out.println("-------> afterInvoke:"+msg);
}
private String convertArgs(Object[] args)
{
if(args==null || args.length==0)
{
return null;
}
StringBuilder sb= new StringBuilder();
for(Object object : args)
{
sb.append(object.toString());
}
return sb.toString();
}
//在这里就把代理对象创建出来
public Object getProxyObject(Object proxied) {
this.proxied = proxied;
return Proxy.newProxyInstance(
this.proxied.getClass().getClassLoader(),
this.proxied.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforeInvoke("proxy name:"+proxy.getClass().getName());
beforeInvoke("proxied name:"+proxied.getClass().getName());
beforeInvoke( "args:"+convertArgs(args));
Object o = method.invoke(proxied,args);
afterInvoke("result:"+o);
return o;
}
}
//main
public class Main {
public static void main(String[] args) {
System.out.println("##############");
System.out.println("-------> second call:");
UserService userService = (UserService) new DynamicProxy().getProxyObject(new UserServiceImpl());
User user1 = userService.addUser();
userService.editUser(user1);
userService.deleteUser(user1.getUserId());
}
}
六、使用cglib动态代理
cglib可以代理非接口类,但是因为其实现原理是继承,所以无法代理被代理类中final方法,也无法代理final修饰的类。
代理类需要实现MethodInterceptor 接口
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.8</version>
</dependency> </dependencies> public class CglibDynamicProxy implements MethodInterceptor {
private Object proxied; //Generate a new class if necessary and uses the specified callbacks (if any) to create a new object instance.
//Uses the no-arg constructor of the superclass.
//动态生成一个新的类,使用父类的无参构造方法创建一个指定了特定回调的代理实例
public Object getProxyObject(Object proxied)
{
this.proxied = proxied;
//增强器,动态代码生成器
Enhancer enhancer = new Enhancer();
//回调方法
enhancer.setCallback(this);
//设置生成类的父类类型
enhancer.setSuperclass(proxied.getClass());
//动态生成字节码并返回代理对象
return enhancer.create();
} public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { beforeInvoke("Object:"+o.getClass().getName());
beforeInvoke("method:"+method.getName());
beforeInvoke("args:"+convertArgs(objects));
beforeInvoke("methodProxy:"+methodProxy.getSignature());
Object result = methodProxy.invoke(this.proxied,objects);
afterInvoke("result:"+result);
return result;
} private void beforeInvoke(String msg)
{
System.out.println("-------> beforInvoke:"+msg);
} private void afterInvoke(String msg)
{
System.out.println("-------> afterInvoke:"+msg);
} private String convertArgs(Object[] args)
{
if(args==null || args.length==0)
{
return null;
}
StringBuilder sb= new StringBuilder();
for(Object object : args)
{
sb.append(object.toString());
} return sb.toString();
}
}
main:
public class Main {
public static void main(String[] args) {
System.out.println("##############");
System.out.println("-------> 4 call:");
UserService service4 = (UserService)new CglibDynamicProxy().getProxyObject(new UserServiceImpl());
User user4 = service4.addUser();
service4.editUser(user4);
service4.deleteUser(user4.getUserId());
}
}
java动态代理(JDK和CGLIB)笔记的更多相关文章
- CGLIB和Java动态代理的区别(笔记)
java常用知识点: 1.Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承):CGLIB能够代理普通类:2.Jav ...
- 动态代理jdk和cglib的区别
学习来源贴:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类, ...
- 动态代理(JDK、CGLIB)
JDK-Proxy(动态代理): 特点:要求被代理的对象必须接口 缺点:如果一个对象没有任何接口实现,则不能使用JDK动态代理 1.创建一个Animal 提供一个方法 2.创建一个cat类.实现Ain ...
- Java动态代理-JDK自带实现
上篇文章讲解了什么是静态代理,但是静态代理有一个问题就是需要建立很多的代理类,这样我们需要修改代理的方法的时候,需要在每个类中都要修改,这对于我们来说:当代理类很多的时候工作量就会成倍的增加. 于是针 ...
- Java动态代理 ----- jdk代理与cglib代理
1.jdk代理 针对接口进行代理,接口可以没有方法, InvocationHandler会拦截所有方法,不过好像意义不大....只能执行Object类的方法,执行结果有点奇怪... package t ...
- [转]java动态代理(JDK和cglib)
转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理 ...
- java动态代理(JDK和cglib)
转:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代 ...
- 《转》JAVA动态代理(JDK和CGLIB)
该文章转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的 ...
- 《转》java动态代理(JDK和cglib)
该文章转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的 ...
- java动态代理(JDK和cglib实现对比)
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt214 JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特 ...
随机推荐
- 南京Uber优步司机奖励政策(1月4日~1月10日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- C#第一阶段——结构体
概念理解: 很多相互联系的信息可以组成一个整体.比如一个学生的信息包括学号.姓名.性别.年龄等,它们紧密联系,共同描述学生的状况.在 C#中我们可以把这些紧密联系变量定义成结构体(Str ...
- Python破解压缩包密码问题
所用知识 1. Pool 进程池 2. try...except 异常处理 3.枚举的方式 4.生成器的运用 逻辑关系 通过生成假密码去碰撞!捕获异常,一直碰撞,直到生成的密码与压缩包建立的密码对应, ...
- python 3.6 setup
1.添加python3.6安装包,并且安装 sudo apt-get install software-properties-common 2.下载python3.6 sudo add-apt-rep ...
- Richardson成熟度模型
Richardson Maturity Model(RMM) 迈向REST的辉煌 一个模型(由Leonard Richardson开发)将REST方法的主要元素分解为三个步骤.这些引入资源,http动 ...
- PLSQL集合类型
PLSQL集合类型 --联合数组(索引表) /* 用于存储某个数据类型的数据集合类型 .通过索引获得联合数组中得值 如下例子: */ DECLARE CURSOR cur_chars IS SEL ...
- hdu2037今年暑假不AC(贪心,活动安排问题)
今年暑假不AC Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submi ...
- python3 BeautifulSoup模块使用
BeautifulSoup就是Python的一个HTML或XML的解析库,可以用它来方便地从网页中提取数据.官方解释如下: Beautiful Soup提供一些简单的.Python式的函数来处理导航. ...
- 手机APP测试如何进行兼容性测试?
Android App兼容性测试是一个比较重要的App评价内容,实际上兼容性测试不仅仅和测试人员相关,在开发阶段就应当着重考虑,因为兼容性问题是除了实现App本身要求的功能后,必须要关注.而且至关重要 ...
- 第四篇 与Flask相关的插件(flask-session、wtforms)
公司中使用SQL的种方式: 1. 写Django:ORM(关系对象映射), 2. 写Flask和其他:有两种方式: (1) 原生SQL:使用原生SQL有两种选择: A. pymysql (python ...