Java之使用动态代理笔记

考虑这样一个场景:
假如你需要扩展某个方法的功能, 例如在调用该方法前打印日志,直接修改原方法是一个方案,但是以后又要求把打印功能去掉呢?。本着"对修改封闭,对扩展开放"的原则",可以考虑使用动态代理。下面的例子展示了如何使用动态代理。
—>详细原理到这个链接

JDK动态代理

首先,构造一个简单的JDK动态代理类需要以下元素:
1.接口
2.接口实现类
3.InvocationHandler实现类
4.通过Proxy.newProxyInstance方法生成代理类对象

JDK动态代理只能针对实现了接口的类进行代理


例子

// 接口
public interface Star {
    void sing();
    void dance();
}
// 接口实现类
public class StarImpl implements Star{

    @Override
    public void dance(){
        System.out.println("He is dancing.");
    }

    @Override
    public void sing(){
        System.out.println("he is singing.");
    }

}
// InvocationHandler实现类
public class StarInvocationHandler implements InvocationHandler{

    //代理的目标对象
    private Object target;

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

    @Override
    //proxy 调用方法的代理实例
    public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {

        // 增强的方法
        if(method.getName().equals("sing"))
        {
            System.out.println("唱歌之前的热身");
        }

        if(method.getName().equals("dance"))
        {
            System.out.println("跳舞之前的热身");
        }

       //  将请求转发给目标对象
        return method.invoke(target, args);
    }
}
\\ 测试
 Star star = new StarImpl();
 Star starProxy = (Star)Proxy.newProxyInstance(star.getClass().getClassLoader(),
                                               star.getClass().getInterfaces(),
                                              new StarInvocationHandler(star));
starProxy.dance();

运行结果:
跳舞之前的热身
He is dancing.

让我们看看Proxy的构造动态代理对象的方法:

public static Object newProxyInstance(ClassLoader loader,
                                   Class<?>[] interfaces,
                                     InvocationHandler h)

前两个参数是基于被代理对象调用的,因此,InvocationHandler 的实现将定义我们的额外操作。

动态代理的工作模式就是:将增强的方法实现交给InvocationHandler, 当外界对Proxy角色的每一个方法调用, Proxy都会交给InvocationHandler来处理, 而InvocationHandler则调用具体的对象(realObject)的方法.

Proxy——> InvocationHandler——>realObject

CGLib动态代理

首先,构造一个简单的CGLib动态代理类需要以下元素:
1.代理的目标类
2.MethodInterceptor实现类
3.使用Enhancer 类生成代理类对象

CGLib动态代理适用于没有实现接口的类进行代理


例子

// 目标类
public class StarAct {
    
    public void act(){
        System.out.println("The star is acting");
    }
}
// 实现方法拦截器
public class StartIntercepter implements MethodInterceptor {

    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable{
        System.out.println("演出时要拦截观众.");
        methodProxy.invokeSuper(o, objects);
        return o;
    }
}
// 测试类
public class proxyTest {

    public static void main(String[] args) {
        // 使用CGLib做动态代理
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(StarAct.class);
        enhancer.setCallback(new StartIntercepter());

        StarAct starAct = (StarAct)enhancer.create();
        starAct.act();
    }
}  
// 运行结果:
演出时要拦截观众.
The star is acting
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值