Java动态代理的两种方式

动态代理

基于JDK的动态代理

基于接口

委托类和代理类实现的公共接口 Subject.java

package com.lvshui5u.test.jdkproxy;
/**
 * @author: lvshui5u
 * @date: 2021/5/28 10:22
 * @describe: 基于jdk的动态代理
 *
 * 1. 创建一个接口(被代理)
 * 2. 实现接口
 * 3. 创建代理类,实现InvocationHandler接口
 * 4. 代理类的调用,用Proxy类创建实例
 */
public interface Subject {
    void hello(String str);
    void bye(String str);
}

实现公共接口的具体委托类 SubjectImpl.java

package com.lvshui5u.test.jdkproxy;

/**
 * @author: lvshui5u
 * @date: 2021/5/28 10:28
 * @describe:
 */
public class SubjectImpl implements Subject {
    @Override
    public void hello(String str) {
        System.out.println("hello "+str);
    }

    @Override
    public void bye(String str) {
        System.out.println("bye "+str);
    }
}

对委托类的处理,实现InvocationHandler接口,具体实现一个invoke方法 SubjectProxy.java

package com.lvshui5u.test.jdkproxy;

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

/**
 * @author: lvshui5u
 * @date: 2021/5/28 10:30
 * @describe:
 */
public class SubjectProxy implements InvocationHandler {
    private Subject subject;

    public SubjectProxy(Subject subject) {
        this.subject = subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("--- start ---");
        // 利用反射调用类里面的实际方法
        Object invoke = method.invoke(subject, args);
        System.out.println("--- end ---");
        return invoke;
    }
}

代理类的实现,调用Proxy类的newProxyInstance方法

package com.lvshui5u.test.jdkproxy;

import java.lang.reflect.Proxy;

/**
 * @author: lvshui5u
 * @date: 2021/5/28 10:35
 * @describe:
 */
public class SubjectMain {
    public static void main(String[] args) {
        Subject subject = new SubjectImpl();
        SubjectProxy subjectProxy = new SubjectProxy(subject);
        // 代理类的类加载器  被代理类的接口(们) 代理类实例
        Subject instance = (Subject) Proxy.newProxyInstance(subjectProxy.getClass().getClassLoader(),
                subject.getClass().getInterfaces(),
                subjectProxy);
        instance.hello("world");
        instance.bye("world");
    }
}

输出

--- start ---
hello world
--- end ---
--- start ---
bye world
--- end ---

基于CGLIB的动态代理

基于继承,原理是对代理的目标类生成一个子类,并覆盖其中方法实现增强。

委托类 Subject.java

package com.lvshui5u.test.cglibproxy;

/**
 * @author: lvshui5u
 * @date: 2021/5/28 10:55
 * @describe: 基于cglib的动态代理
 *
 * 1. 创建被代理类
 * 2. 创建方法拦截器,实现MethodInterceptor接口
 * 3. 用Enhancer 生成被代理类
 */
public class Subject {
    public void hello(String str){
        System.out.println("hello " +str);
    }

    public void bye (String str){
        System.out.println("bye " +str);
    }
}

方法拦截器,实现MethodInterceptor接口,对方法进行拦截并增强

package com.lvshui5u.test.cglibproxy;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @author: lvshui5u
 * @date: 2021/5/28 10:56
 * @describe:
 */
public class SubjectInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("--- start ---");
        Object invoke = methodProxy.invokeSuper(o, objects);
        System.out.println("--- end ---");
        return invoke;
    }
}

创建增强器,增强器创建代理类

package com.lvshui5u.test.cglibproxy;

import net.sf.cglib.proxy.Enhancer;

/**
 * @author: lvshui5u
 * @date: 2021/5/28 11:08
 * @describe:
 */
public class SubjectMain {
    public static void main(String[] args) {
        // 增强器
        Enhancer enhancer = new Enhancer();
        // 指定代理类
        enhancer.setSuperclass(Subject.class);
        // 设置回调,对于代理类上所有方法的调用,会调用callback,callback实现需要interceptor()
        enhancer.setCallback(new SubjectInterceptor());
        Subject subject = (Subject) enhancer.create();
        subject.hello("world");
        subject.bye("world");
    }
}

输出

--- start ---
hello world
--- end ---
--- start ---
bye world
--- end ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值