动态代理:为一堆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)笔记的更多相关文章

  1. CGLIB和Java动态代理的区别(笔记)

    java常用知识点: 1.Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承):CGLIB能够代理普通类:2.Jav ...

  2. 动态代理jdk和cglib的区别

    学习来源贴:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类, ...

  3. 动态代理(JDK、CGLIB)

    JDK-Proxy(动态代理): 特点:要求被代理的对象必须接口 缺点:如果一个对象没有任何接口实现,则不能使用JDK动态代理 1.创建一个Animal 提供一个方法 2.创建一个cat类.实现Ain ...

  4. Java动态代理-JDK自带实现

    上篇文章讲解了什么是静态代理,但是静态代理有一个问题就是需要建立很多的代理类,这样我们需要修改代理的方法的时候,需要在每个类中都要修改,这对于我们来说:当代理类很多的时候工作量就会成倍的增加. 于是针 ...

  5. Java动态代理 ----- jdk代理与cglib代理

    1.jdk代理 针对接口进行代理,接口可以没有方法, InvocationHandler会拦截所有方法,不过好像意义不大....只能执行Object类的方法,执行结果有点奇怪... package t ...

  6. [转]java动态代理(JDK和cglib)

    转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理 ...

  7. java动态代理(JDK和cglib)

    转:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代 ...

  8. 《转》JAVA动态代理(JDK和CGLIB)

    该文章转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的 ...

  9. 《转》java动态代理(JDK和cglib)

    该文章转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的 ...

  10. java动态代理(JDK和cglib实现对比)

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt214 JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特 ...

随机推荐

  1. 《C++ Primer》第II部分:C++标准库

    <C++ Primer>第II部分:C++标准库 前言 把<C++ Primer>读薄系列笔记.本篇为第II部分C++标准库,包含全书第8-12章重难点: IO库 顺序容器 范 ...

  2. 【LG4175】[CTSC2008]网络管理

    [LG4175][CTSC2008]网络管理 题面 洛谷 题解 感觉就和普通的整体二分差不太多啊... 树上修改就按时间添加,用树状数组维护一下即可 代码 #include<iostream&g ...

  3. 一文带你了解 Raft 一致性协议的关键点

    此文已由作者孙建良授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Raft 协议的发布,对分布式行业是一大福音,虽然在核心协议上基本都是师继 Paxos 祖师爷(lampor ...

  4. hadoop 家族图

    hadoop家族

  5. 后续博客转移到zhylj.cc

    此博客暂不更新了 zhylj.cc

  6. InnoDB锁冲突案例演示(续)

      Preface       I've demontstrated several InnoDB locking cases in my previous blog.I'm gonna do the ...

  7. Linux命令应用大词典-第28章 硬件管理

    28.1 lscpu:显示有关CPU架构的信息 28.2 nproc:显示当前进程可用的CPU数目 28.3 chcpu:配置CPU

  8. Linux命令应用大词典-第16章 归档和压缩

    16.1 tar:进行归档和压缩 16.2 gzip:压缩或解压缩gzip文件 16.3 gunzip:解压缩gzip文件 16.4 zcmp:比较gzip压缩文件 16.5 zdiff:比较gzip ...

  9. 推荐:一个适合于Python新手的入门练手项目

    随着人工智能的兴起,国内掀起了一股Python学习热潮,入门级编程语言,大多选择Python,有经验的程序员,也开始学习Python,正所谓是人生苦短,我用Python 有个Python入门练手项目, ...

  10. [JSON].connectionValue()

    语法: [JSON].connectionValue() 说明: 将对象的所有键值接连成新的字符串值 返回: [String] 示例: Set a = toJson() c = Array(1,2,3 ...