动态代理:为一堆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++ 面向对象程序设计

    1. OOP:概述 2. 定义基类和派生类 3. 虚函数 4. 抽象基类 5. 访问控制与继承 6. 继承中的类作用域 7. 构造函数与拷贝控制 8. 容器与继承

  2. EF Core ThenInclude 2.0自动完成提示有误,坑了一下

    只要代码正确,可以编译运行的... https://github.com/dotnet/roslyn/issues/8237

  3. 使用Google Cloud Messaging (GCM),PHP 开发Android Push Notifications (安卓推送通知)

    什么是GCM? Google Cloud  Messaging (GCM) 是Google提供的一个服务,用来从服务端向安卓设备发送推送通知. GCM分为客户端和服务端开发. 这里我们只介绍服务端开发 ...

  4. libevent学习三(Getting an event_base)

    1.一个event_base持有了一系列的事件,并监控和决定哪些事件需要激活, 2.每一个event_base背后都有一个支持其工作的方法(诸如select,poll,epoll,kquene...) ...

  5. 读google c++规范笔记

    全局变量在main函数之前初始化原则上禁止拷贝构造函数和赋值函数如果只有数据,没有方法,可以用struct析构函数声明为虚函数尽量避免重载操作符 难以定位的bug 误以为简单的操作存取控制 可以放到声 ...

  6. create-react-app react-redux项目 配置模块热更新hmr

    HRM并不是create-react-app专属的,提供一篇博客介绍hrm http://chrisshepherd.me/posts/adding-hot-module-reloading-to-c ...

  7. 逆波兰表达式[栈 C 语言 实现]

    逆波兰表达式 逆波兰表达式又叫做后缀表达式.在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表示.波兰逻辑学家J.Lukasiewicz于1929年提出了另一种表示 ...

  8. ObjectMapper的使用

    Jackson ObjectMapper类 ObjectMapper类是Jackson库的主要类它提供一些功能将Java对象转换成JSON结构,反之亦然它使用JsonParser和JsonGenera ...

  9. Ext JS 6学习文档-第5章-表格组件(grid)

    Ext JS 6学习文档-第5章-表格组件(grid) 使用 Grid 本章将探索 Ext JS 的高级组件 grid .还将使用它帮助读者建立一个功能齐全的公司目录.本章介绍下列几点主题: 基本的 ...

  10. 编译安装hadoop2.6.3

    一.安装环境 1.1  JAVA  安装java1.7 下载jdk1.7: [root@node1~]# wget http://download.oracle.com/otn-pub/java/jd ...