前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JDK动态代理

JDK动态代理

作者头像
itlemon
发布2020-04-03 14:40:15
发布2020-04-03 14:40:15
54100
代码可运行
举报
文章被收录于专栏:深入理解Java深入理解Java
运行总次数:0
代码可运行

JDK动态代理是java.lang.reflect.*包提供的方式,它必须借助一个接口才能产生一个对象,也就是说JDK动态代理是对接口的代理。一般要使用JDK动态代理,首先得定义接口,然后再对这个接口的实现类对象进行代理,产生代理对象。SpringAOP就是JDK动态代理的应用之一。

第一步:定义接口

JDK动态代理必须有接口,这里仅仅定义一个及其简单的接口用于示例。

代码语言:javascript
代码运行次数:0
运行
复制
package com.lemon.designmode.interfaces;

/**
 * @author lemon
 * @date 2018/2/11 上午10:25
 */
public interface HelloWorld {

    void sayHello();
}

第二步:实现接口

这里是接口的实现类,具体的业务逻辑写在这里。

代码语言:javascript
代码运行次数:0
运行
复制
package com.lemon.designmode.bean;

import com.lemon.designmode.interfaces.HelloWorld;

/**
 * @author lemon
 * @date 2018/2/11 上午10:23
 */
public class HelloWorldImpl implements HelloWorld {

    @Override
    public void sayHello() {
        System.out.println("向Java世界问好...");
    }
}

这里是最简单的Java接口和实现类的关系,此时可以开始动态代理了,一般会分为两个步骤:第一是建立代理对象和真实服务对象的代理和被代理关系,第二步是实现代理对象具体方法的逻辑。

第三步:动态代理绑定和代理逻辑实现

JDK动态代理中,要实现代理逻辑类必须娶实现java.lang.reflect.InvocationHandler接口,它内部定义了一个invoke方法,并提供接口数组用于将代理对象下挂到被代理对象所属的接口下,也就是说代理对象和被代理对象都是实现了同一个接口,只不过被代理对象是显式实现(使用了关键字implements),代理对象是运行时实现。

代码语言:javascript
代码运行次数:0
运行
复制
package com.lemon.designmode.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author lemon
 * @date 2018/2/11 上午10:27
 */
public class JdkProxyExample implements InvocationHandler {

    private Object target;

    /**
     * 该方法用于将真实对象绑定到代理类,并返回代理对象
     *
     * @param target 真实服务对象
     * @return 代理对象
     */
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    /**
     * 代理方法逻辑
     *
     * @param proxy  代理对象
     * @param method 当前调度方法
     * @param args   被代理对象的方法需要的参数
     * @return 代理结果
     * @throws Throwable 异常
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("进入代理方法");
        System.out.println("代理方法调用真实对象之前的逻辑处理");
        Object obj = method.invoke(target, args);
        System.out.println("代理方法调用真实对象之后的逻辑处理");
        return obj;
    }
}

上面的代码实现了两步:第一是将真实服务对象和代理对象进行了绑定;第二步是实现了代理逻辑。 这里通过bind方法将真实服务对象保存到了代理类的成员变量中,并返回了代理对象。

newProxyInstance方法分析: 1)第一个参数是类加载器,这里使用的是target的类加载器 2)第二个参数是传入真实服务对象所在的接口,用于将代理对象下挂到和真实服务对象所在的接口 3)第三个参数是定义实现方法逻辑的代理类,this表示当前类对象,也就是代理类,那么这个代理类就必须实现InvocationHandler接口的invoke方法,它就是代理逻辑的实现方法。

invoke方法分析: 1)第一个参数是代理对象,就是bind方法生成的对象 2)第二个参数是当前调度的方法 3)第三个参数是调度方法的参数。

第四步:测试JDK动态代理

代码语言:javascript
代码运行次数:0
运行
复制
package com.lemon.designmode.test;

import com.lemon.designmode.bean.HelloWorldImpl;
import com.lemon.designmode.interfaces.HelloWorld;
import com.lemon.designmode.proxy.JdkProxyExample;

/**
 * @author lemon
 * @date 2018/2/11 上午10:44
 */
public class JdkProxyTest {

    public static void main(String[] args) {
        JdkProxyExample jdkProxyExample = new JdkProxyExample();
        HelloWorld proxy = (HelloWorld) jdkProxyExample.bind(new HelloWorldImpl());
        proxy.sayHello();
    }
}

这里使用代理对象直接调用真实服务对象同名方法,实现了零入侵式代码增强。Spring AOP就是这个原理,在真实服务对象方法加入前置通知、后置通知、环绕通知等。 测试方法运行结果如下:

代码语言:javascript
代码运行次数:0
运行
复制
进入代理方法
代理方法调用真实对象之前的逻辑处理
向Java世界问好...
代理方法调用真实对象之后的逻辑处理
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018/02/11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第一步:定义接口
  • 第二步:实现接口
  • 第三步:动态代理绑定和代理逻辑实现
  • 第四步:测试JDK动态代理
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档