前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >动态代理技术的运用

动态代理技术的运用

作者头像
每天学Java
发布2020-06-02 10:06:50
2810
发布2020-06-02 10:06:50
举报
文章被收录于专栏:每天学Java

在前一篇文章我们了解了Spring AOP的简单运用,我们发现面向切面编程的核心是动态代理,我们这篇文章主要就是看一下:JDK自带的动态代理和CGLIB的动态代理

注:JDK实现动态代理方式需要被代理的类拥有接口,CGLIB方式要求被代理类没有被final修饰

相关文章:Spring AOP的简单应用

Class类文件结构

01

JDK动态代理技术

首先定义一个接口

代码语言:javascript
复制
interface SuperObject {
    void execute();
}

被代理类:

代码语言:javascript
复制
class RealObject implements SuperObject {

    @Override
    public void execute() {
        System.out.println("执行方法");
    }
}

声明一个代理类需要我们实现reflect包下面的一个接口InvocationHandler。其中invoke方法我们大概看一下proxy就是被代理的类了,其中Method也是reflect包下的类,代表了类的方法。

代码语言:javascript
复制
public class JdkProxy  implements InvocationHandler{
    @Override
    public Object invoke(Object proxy, Method method,         Object[] args) throws Throwable {
        return null;
    }
}

代理类对被代理类进行方法的增强:

代码语言:javascript
复制
public class JdkProxy implements InvocationHandler {
    private Object target;

    public JdkProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置方法");
        Object o = method.invoke(target, args);
        System.out.println("后置方法");
        return o;
    }

}

测试:Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)返回某个对象的代理对象。其中第一个参数是类加载器,第二个参数是代理类实现的接口,这也是我们说为什么要代理类要实现接口才行。第三个参数是调用处理器,调用实现了InvocationHandler 类的一个回调方法

代码语言:javascript
复制
    public static void main(String[] args) {
        SuperObject superObject = (SuperObject)
                Proxy.newProxyInstance(RealObject.class.getClassLoader(),
                RealObject.class.getInterfaces(),
                new JdkProxy(new RealObject()));
        superObject.execute();
    }

结果:

代码语言:javascript
复制
Connected to the target VM, address: '127.0.0.1:50982', transport: 'socket'
前置方法
执行方法
后置方法
Disconnected from the target VM, address: '127.0.0.1:50982', transport: 'socket'

02

CGLib动态代理技术

使用CGLIB实现动态代理需要我们引入Jar包,这里我导入相应的依赖文件

代码语言:javascript
复制
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.10</version>
</dependency>

定义被代理的类,这个类实现MethodInterceptor,可以理解为方法拦截器,并且实现其方法intercept。

代码语言:javascript
复制
public class ProxySubject implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz) {
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
 //用于创建无参的目标对象代理类,对于有参构造器则调用Enhancer.create(Class[] argumentTypes, Object[] arguments),第一个参数表示参数类型,第二个参数表示参数的值。
        return enhancer.create();   
    }

    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("前置方法");
        Object result = methodProxy.invokeSuper(object, args);
        System.out.println("后置方法");
        return result;
    }
}

测试:

代码语言:javascript
复制
public class Main {
    public static void main(String[] args) {
        RealSubject subject = (RealSubject) new ProxySubject().getProxy(RealSubject.class);
        subject.sayHello();
   
    }
}

结果:

代码语言:javascript
复制
Connected to the target VM, address: '127.0.0.1:50982', transport: 'socket'
前置方法
hello
后置方法
Disconnected from the target VM, address: '127.0.0.1:50982', transport: 'socket'

到这里就介绍了JDK与CGLib两种动态代理技术,最近自己空闲时间也在研究关于Spring AOP的实现源码,发现了不少新的东西:比如ASM和拦截链,ASM框架是一个致力于字节码操作和分析的框架,它可以用来修改一个已存在的类或者动态产生一个新的类,换句话说他可以修改class文件,前面我们有一篇文章聊到了class文件说明,在一些博客上我看到有人说一些高手可以直接修改class文件,来修改方法,大家可以私下研究研究。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 每天学Java 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档