实战CGLib系列文章 MethodInterceptor和Enhancer

实战CGLib系列文章

本篇介绍通过MethodInterceptor和Enhancer实现一个动态代理。

一、首先说一下JDK中的动态代理:

JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的,不了解的同学请参考我的这篇Blog:Java动态代理详解 http://shensy.iteye.com/blog/1698197

但是,JDK中所要进行动态代理的类必须要实现一个接口,也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编程中具有一定的局限性,而且使用反射的效率也并不是很高。

二、使用CGLib实现:

使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

下面,将通过一个实例介绍使用CGLib实现动态代理。

1、被代理类:

首先,定义一个类,该类没有实现任何接口,包含两个方法。

Java代码

public class ConcreteClassNoInterface {

public String getConcreteMethodA(String str){  

    System.out.println("ConcreteMethod A ... "+str);  

    return str;  

}  

public int getConcreteMethodB(int n){  

    System.out.println("ConcreteMethod B ... "+n);  

    return n+10;  

}  

}

2、拦截器:

定义一个拦截器。在调用目标方法时,CGLib会回调MethodInterceptor接口方法拦截,来实现你自己的代理逻辑,类似于JDK中的InvocationHandler接口。

Java代码

public class ConcreteClassInterceptor implements MethodInterceptor{

public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {  

    System.out.println("Before:"+method);    

    Object object=proxy.invokeSuper(obj, arg);  

    System.out.println("After:"+method);   

    return object;  

}  

}

参数:Object为由CGLib动态生成的代理类实例,Method为上文中实体类所调用的被代理的方法引用,Object[]为参数值列表,MethodProxy为生成的代理类对方法的代理引用。

返回:从代理实例的方法调用返回的值。

其中,proxy.invokeSuper(obj,arg):

调用代理类实例上的proxy方法的父类方法(即实体类ConcreteClassNoInterface中对应的方法)

在这个示例中,只在调用被代理类方法前后各打印了一句话,当然实际编程中可以是其它复杂逻辑。

3、生成动态代理类:

Java代码

Enhancer enhancer=new Enhancer();

enhancer.setSuperclass(ConcreteClassNoInterface.class);

enhancer.setCallback(new ConcreteClassInterceptor());

ConcreteClassNoInterface ccni=(ConcreteClassNoInterface)enhancer.create();

这里Enhancer类是CGLib中的一个字节码增强器,它可以方便的对你想要处理的类进行扩展,以后会经常看到它。

首先将被代理类ConcreteClassNoInterface设置成父类,然后设置拦截器ConcreteClassInterceptor,最后执行enhancer.create()动态生成一个代理类,并从Object强制转型成父类型ConcreteClassNoInterface。

最后,在代理类上调用方法:

Java代码

ccni.getConcreteMethodA(“shensy”);

ccni.getConcreteMethodB(0);

查看控制台输出:

控制台代码

Before :public java.lang.String generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodA(java.lang.String)

ConcreteMethod A … shensy

After :public java.lang.String generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodA(java.lang.String)

Before :public int generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodB(int)

ConcreteMethod B … 0

After :public int generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodB(int)

可以看到,拦截器在调用被代理类方法前后都执行了print操作。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
org.springframework.cglib.proxy.MethodInterceptorCGLIB库中的接口,用于实现方法拦截器,可以在方法调用前后进行某些操作。 使用步骤如下: 1. 实现MethodInterceptor接口,并重写intercept方法。 2. 创建Enhancer对象,用于生成代理类。 3. 设置代理类的父类、接口、方法拦截器等属性。 4. 调用create方法创建代理类。 5. 使用代理类进行方法调用。 示例代码如下: ``` // 实现MethodInterceptor接口 public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("before method " + method.getName()); Object result = proxy.invokeSuper(obj, args); System.out.println("after method " + method.getName()); return result; } } // 创建Enhancer对象 Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserServiceImpl.class); enhancer.setCallback(new MyMethodInterceptor()); // 创建代理类 UserServiceImpl userService = (UserServiceImpl) enhancer.create(); // 使用代理类调用方法 userService.addUser(new User()); ``` 在上述示例中,我们创建了一个名为MyMethodInterceptor的方法拦截器,并在intercept方法中输出了方法调用前后的日志信息。然后,我们创建了一个Enhancer对象,并设置了代理类的父类和方法拦截器。最后,我们使用Enhancer对象的create方法创建了代理类,并使用代理类调用了addUser方法。在方法调用时,MyMethodInterceptor会被触发,输出方法调用前后的日志信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值