「这是我参与2022首次更文挑战的第31天,活动详情查看:2022首次更文挑战」。
一、什么是Cglib代理
静态代理和动态代理都要求目标对象是一个接口的实现类,但有时候我们就是一个单独的对象,并没有实现任何接口。这个时候就可以使用Cglib代理的方式实现代理,Cglib代理也叫子类代理,是通过在运行的过程中实现一个子类的对象,从而达到对目标对象的扩展的目的。
二、Cglib代理模式的实现
cglib的使用需要引入相应的jar包。
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
<scope>compile</scope>
</dependency>
上述方式引入了cglib的包,以便于接下来使用cglib。
public class WholesaleShop003 {
public void sell() {
System.out.println("啤酒售卖价格2元");
}
}
没有实现任何接口的批发商对象,售卖啤酒
public class ShopProxy003 implements MethodInterceptor {
private Object target;
public ShopProxy003(Object target) {
this.target = target;
}
public Object getProxyInstance() {
Enhancer en = new Enhancer();
en.setSuperclass(target.getClass());
en.setCallback(this);
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object invoke = method.invoke(target, args);
System.out.println("跑腿费2元");
return invoke;
}
}
实现MethodInterceptor,需要实现intercept方法,这个就是对方法进行拦截然后进行增强。此外,需要编写一个获取代理对象的方法。
public static void main(String[] args) {
WholesaleShop003 shop = new WholesaleShop003();
WholesaleShop003 proxy = (WholesaleShop003)new ShopProxy003(shop).getProxyInstance();
proxy.sell();
}
通过ShopProxy003获取代理对象,然后执行对象自身的方法,在被intercept后,成功进行了增强。如果对sell方法加上final或者static,方法的增强均会失效。
三、总结
Cglib可以在运行期扩展java类与实现java接口,在运行期间可以进行拦截。spring的aop就使用了cglib。
注意:
- 如果目标是单独的对象,那么目标对象不能是final的,因为cglib拦截过后会创建子类,如果是final的对象,会直接抛出异常。
- 目标对象的方法不能是final或者static的,无法实现增强效果。