动态代理

jdk动态代理

作用:动态代理可以在不改变原类的情况下对该类的功能进行增强,在动态代理中我们不需要写代理类即可对该类进行增强。
例如:当导演要找演员演电影时,我们不会去自己找演员,而是找演员的经纪人,经纪人对演员能做什么进行规定。演员只负责演电影。
而在动态代理中我们可以通过InvocationHandler类生成代理。

要使用动态代理,该类必须实现一个接口

public interface SuperStarCan {
    void play();
}
public class SuperStar implements SuperStarCan {

    @Override
    public void play() {
        System.out.println("我决定出演这部戏");
    }
}

写一个invocationH。。。的实现类,实现该接口的类必须重写invoke方法,

public class InvocationHandlerImpl implements InvocationHandler {
    //要代理的真实对象
    private Object target;
    //构造方法,给我们要代理的真实对象赋初始值
    public InvocationHandlerImpl(Object target){
        this.target=target;
    }


    /**
     *该方法集中处理动态代理类上的所有方法调用
     * 调用 处理器根据这三个参数进行预处理或分派到委托实例上反射执行
     * @param proxy 代理类实例
     * @param method 被调用的方法对象
     * @param args  调用方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //当代理对象调用真实对象的方法时,它会自动地跳转到代理对象关联地handler对象地invoke方法进行调用
        Object invoke = method.invoke(target, args);
        return invoke;
    }

}

创建一个测试类

class InvocationHandlerImplTest {
@Test
    void createDynamicProxyAbdInvoke(){
    SuperStarCan superStar = new SuperStar();
    InvocationHandler invocationHandler = new InvocationHandlerImpl(superStar);
    SuperStarCan proxyInstance = (SuperStarCan) Proxy.newProxyInstance(superStar.getClass().getClassLoader(), superStar.getClass().getInterfaces(), invocationHandler);
    proxyInstance.play();
}

}

CGLIB动态代理

与jdk动态代理相比,使用的类不用实现某个接口,不过得引入对应得包
CGLib 的原理是对指定目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对 final 修饰的类进行代理。

dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

<dependency>
    <groupId>org.ow2.asm</groupId>
    <artifactId>asm</artifactId>
    <version>9.2</version>
</dependency>
public class SuperStar  {

    
    public void play() {
        System.out.println("我决定出演这部戏");
    }
}

public class StarProxy implements MethodInterceptor {
    private Object target;

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


    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        //调用父类的方法
        Object result = proxy.invokeSuper(object, args);
        return result;
    }
}

class StarProxyTest {
    @Test
    void test(){
    SuperStar superStar = new SuperStar();
    StarProxy starProxy = new StarProxy(superStar);
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(superStar.getClass());
        enhancer.setCallback(starProxy);
        SuperStar superStarProxy = (SuperStar) enhancer.create();
        superStarProxy.play();
    }
}

JDK动态代理和CGLIB动态代理的区别

JDK 动态代理,JDK 动态代理的类必须实现一个接口,而且生成的代理类是其接口的实现类,也就是被代理的类的兄弟类,由JDK内部实现,无需引入Jar包
CGLIB代理的类,无需强制实现接口,其生成的代理类是被代理类的子类,并且重写被代理类的方法,而且需要额外的引入Jar
JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。
JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值