博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java动态代理机制
阅读量:5052 次
发布时间:2019-06-12

本文共 3706 字,大约阅读时间需要 12 分钟。

(1)什么是代理?

大道理上讲代理是一种软件设计模式,目的地希望能做到代码重用。具体上讲,代理这种设计模式是通过不直接访问被代理对象的方式,而访问被代理对象的方法。这个就好比 商户---->明星经纪人(代理)---->明星这种模式。我们可以不通过直接与明星对话的情况下,而通过明星经纪人(代理)与其产生间接对话。

 

(2)什么情况下使用代理?

(1)设计模式中有一个设计原则是开闭原则,是说对修改关闭对扩展开放,我们在工作中有时会接手很多前人的代码,里面代码逻辑让人摸不着头脑(sometimes the code is really like shit),这时就很难去下手修改代码,那么这时我们就可以通过代理对类进行增强。

(2)我们在使用RPC框架的时候,框架本身并不能提前知道各个业务方要调用哪些接口的哪些方法 。那么这个时候,就可用通过动态代理的方式来建立一个中间人给客户端使用,也方便框架进行搭建逻辑,某种程度上也是客户端代码和框架松耦合的一种表现。

(3)Spring的AOP机制就是采用动态代理的机制来实现切面编程。

 

(3)静态代理和动态代理

我们根据加载被代理类的时机不同,将代理分为静态代理和动态代理。如果我们在代码编译时就确定了被代理的类是哪一个,那么就可以直接使用静态代理;如果不能确定,那么可以使用类的动态加载机制,在代码运行期间加载被代理的类这就是动态代理,比如RPC框架和Spring AOP机制

 

(4)动态代理类型

  • JDK动态代理
  • CGLIB动态代理

JDK动态代理示例

public interface Manager {    public void modify(String msg);}public class ManagerImpl implements Manager {    @Override    public void modify(String msg) {        System.out.println("*******modify()方法被调用" + msg);    }}
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class BusinessHandler implements InvocationHandler {    public Object delagate = null;        public Object bind(Object obj){        this.delagate = obj;        return Proxy.newProxyInstance(this.delagate.getClass().getClassLoader(), this.delagate.getClass().getInterfaces(), this);    }     @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("do something before method");        Object ret = method.invoke(this.delagate, args);        System.out.println("do something after method");        return ret;    }}public class TestJDKProxy {    public static void main(String[] args) {        // 元对象(被代理对象)        ManagerImpl managerImpl = new ManagerImpl();        // 业务代理类        BusinessHandler securityHandler = new BusinessHandler();        Manager managerProxy = (Manager) securityHandler.bind(managerImpl);        managerProxy.modify("hello steve!");    }}

  

CGLIB动态代理示例

public interface BookFacade {    public void addBook(); }public class BookFacadeImpl implements BookFacade {    @Override    public void addBook() {        System.out.println("增加图书的普通方法...");      }}
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 BookFacadeCglib implements MethodInterceptor {    private Object target;    /**     * 创建代理对象     *      * @param target     * @return     */    public Object getInstance(Object target) {        this.target = target;        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(this.target.getClass());        // 回调方法          enhancer.setCallback(this);        // 创建代理对象          return enhancer.create();    }    @Override    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {        System.out.println("事物开始");        proxy.invokeSuper(obj, args);        System.out.println("事物结束");        return null;    }}
public class TestCglib {    public static void main(String[] args) {        BookFacadeCglib cglib = new BookFacadeCglib();        BookFacade bookCglib = (BookFacade) cglib.getInstance(new BookFacadeImpl());        bookCglib.addBook();    }}

  

两者区别

一、简单来说:

  1. JDK动态代理只能对实现了接口的类生成代理,而不能针对类
  2. CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)

二、Spring在选择用JDK还是CGLiB的依据:

  1. 当Bean实现接口时,Spring就会用JDK的动态代理
  2. 当Bean没有实现接口时,Spring使用CGlib是实现
  3. 可以强制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)

三、CGlib比JDK快?

  1. 使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。
  2. 在对JDK动态代理与CGlib动态代理的代码实验中看,1W次执行下,JDK7及8的动态代理性能比CGlib要好20%左右。

转载于:https://www.cnblogs.com/kaleidoscope/p/9767550.html

你可能感兴趣的文章
18-ES6(1)
查看>>
poj1611 简单并查集
查看>>
Ubuntu 14.04下安装CUDA8.0
查看>>
跨平台开发 -- C# 使用 C/C++ 生成的动态链接库
查看>>
C# BS消息推送 SignalR介绍(一)
查看>>
WPF星空效果
查看>>
WPF Layout 系统概述——Arrange
查看>>
PIGOSS
查看>>
几款Http小服务器
查看>>
iOS 数组排序
查看>>
第三节
查看>>
PHP结合MYSQL记录结果分页呈现(比较实用)
查看>>
Mysql支持的数据类型
查看>>
openSuse beginner
查看>>
Codeforces 620E(线段树+dfs序+状态压缩)
查看>>
Windows7中双击py文件运行程序
查看>>
Market entry case
查看>>
bzoj1230 开关灯 线段树
查看>>
LinearLayout
查看>>
学习python:day1
查看>>