第十二讲-AOP之proxy增强-cglib

第十二讲-AOP之proxy增强-cglib

使用Cglib作为代理的例子

package com.cherry.a12;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxyDemo {
    static class Target{
        public void foo(){
            System.out.println("target foo...");
        }
    }

    public static void main(String[] args) {
        // 准备目标对象
        Target target = new Target();
        Target proxy = (Target)Enhancer.create(Target.class, new MethodInterceptor() {
            @Override             // 代理对象自己  代理类中执行的方法  方法执行时的参数   方法参数
            public Object intercept(Object p, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("before...");
                Object result = method.invoke(target, args);// 执行结果
                System.out.println("after...");
                return result;
            }
        });
        proxy.foo();
    }
}

运行结果如下:

before...
target foo...
after...

使用Cglib实现动态代理的特点:

  • 代理类和目标类是子父的关系(代理类是子类,目标类是父类)
  • 这也带来了一个问题,如果目标类使用了final关键字修饰,那么代理能成功吗?不行,例如将Target类改用final关键字修饰:
static final class Target{
    public void foo(){
        System.out.println("target foo...");
    }
}

则会抛出异常:

Exception in thread "main" java.lang.IllegalArgumentException: Cannot subclass final class com.cherry.a12.CglibProxyDemo$Target
  • 当然,如果目标类的方法使用final关键字修饰,那么使用cglib还是实现功能增强吗,则是不能的:
static class Target{
    public final void foo(){
        System.out.println("target foo...");
    }
}
target foo...

代理的本质就是对方法的重写,既然方法都不能被重写了,自然代理的增强功能也就失去了作用!

目前的Cglib使用的是反射机制来调用目标,但是Cglib还提供了MethodProxy避免发射调用目标方法,如下面的示例(需要的是目标对象):

Target proxy = (Target)Enhancer.create(Target.class, new MethodInterceptor() {
    @Override             // 代理对象自己  代理类中执行的方法  方法执行时的参数   方法参数
    public Object intercept(Object p, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("before...");
        //Object result = method.invoke(target, args);// 执行结果
        Object result = methodProxy.invoke(target, args);	// 使用的不是反射!
        System.out.println("after...");
        return result;
    }
});

运行如下:

before...
target foo...
after...

还有一种是调用invokeSuper()方法 --> 需要的是代理对象:

methodProxy.invokeSuper(p, args);
before...
target foo...
after...
posted @ 2024-07-28 15:03  Cherry_Shen  阅读(50)  评论(0)    收藏  举报