Java的CGLIB

CGLIB

规则:

  • 目标对象:

    不能是final类;

    存在public的构造器;代理创建的目标代理对象需要与public构造器的参数相匹配。

    需要进行增强功能的方法不能是final;

cglib创建代理对象,对方法进行增强

public class HelloWorldCglib {
    private String field;
    public HelloWorldCglib() {

    }

    public HelloWorldCglib(String field) {
        this.field = field;
    }

    public void print() {
        System.out.println("hello world cglib");
    }
}

public class HelloWorldCglibInvocate implements MethodInterceptor {

     /**
     *
     * @param o
     *          目标代理对象
     * @param method
     *          目标方法
     * @param objects
     *          目标方法参数
     * @param methodProxy
     *          方法代理对象
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("hello world proxy before");
        Object obj = methodProxy.invokeSuper(o, objects);
        System.out.println("hello world proxy after");
        return obj;
    }
}

public class ReflectApplication {
    public static void main(String[] args) throws Exception {
        // 设置该属性,是为了生成代理对象的.class类文件 path是类文件存在的位置
        System.setProperty("cglib.debugLocation", "path");
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(HelloWorldCglib.class);
        enhancer.setCallback(new HelloWorldCglibInvocate());
        // 创建的代理对象,需要与public构造器参数相匹配
        HelloWorldCglib proxy1 = (HelloWorldCglib) enhancer.create();
        HelloWorldCglib proxy2 = (HelloWorldCglib) enhancer.create(new Class[] {String.class}, new Object[] {"hello"});
        proxy1.print();
        System.out.println("-------------------");
        proxy2.print();
    }
}

// 结果
hello world proxy before
hello world cglib
hello world proxy after
-------------------
hello world proxy before
hello world hello cglib
hello world proxy after
原理

CGLIB是根据Enhancer根据目标对象(Target,非final类),创建一个目标对象代理类(TargetProxy)。目标对象(Target)作为目标对象代理类(TargetProxy)的父类,TargetProxy重写了Target的所有非final方法。Enhancer为TargetProxy设置了增强功能的CallBack类,最终每当代理类调用代理方法时,都调用CallBack.intercept方法,实现代理功能。

cglib对代理对象的方法进行拦截,然后增强

public class HelloWorldCglib {
    public HelloWorldCglib() {

    }

    public String print2() {
        return "print2";
    }

    public String print3() {
        return "print3";
    }

    public String print4() {
        return "print4";
    }
}

public class HelloWorldCglibInvocate implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("hello world proxy");
        return methodProxy.invokeSuper(o, objects);
    }
}
// 不管原方法返回任何值,该回调会返回固定值
public class HelloWorldFixedValueInvocate implements FixedValue {
    @Override
    public Object loadObject() throws Exception {
        return "fixed value";
    }
}
// 方法拦截,返回的结果是回调数组的下标
public class HelloWorldCglibMethodFilter implements CallbackFilter {
    @Override
    public int accept(Method method) {
        switch (method.getName()) {
            case "print2":
                return 0;
            case "print3":
                return 1;
            case "print4":
                return 2;
        }
        return 0;
    }
}

public class ReflectApplication {
    public static void main(String[] args) throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(HelloWorldCglib.class);
        enhancer.setCallback(new HelloWorldCglibInvocate());
        // 回调数组,方法回调拦截器返回的结果,对应该数组下标index
        // NoOp.INSTANCE 不作任何增强处理
        Callback[] callbacks = new Callback[] {new HelloWorldCglibInvocate(), new HelloWorldFixedValueInvocate(), NoOp.INSTANCE};
        enhancer.setCallbacks(callbacks);
        // 方法回调拦截器
        enhancer.setCallbackFilter(new HelloWorldCglibMethodFilter());
        HelloWorldCglib proxy1 = (HelloWorldCglib) enhancer.create();
        System.out.println(proxy1.print2());
        System.out.println("-------------------");
        System.out.println(proxy1.print3());
        System.out.println("-------------------");
        System.out.println(proxy1.print4());
    }
}
// 结果
hello world proxy
print2
-------------------
fixed value
-------------------
print4
View Code

cglib懒加载对象

Dispatch:回调类,每次访问对象属性(调用getter和setter方法)时都会被触发代理类回调方法。

LazyLoader:回调类,第一次访问对象属性(调用getter方法)时被触发代理类回调方法。

public class HelloWorldCglib {
    private String field;
    public HelloWorldCglib() {

    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

}

public class HelloWorldCglibDispatch implements Dispatcher {
    @Override
    public Object loadObject() throws Exception {
        System.out.println("dispatcher before");
        HelloWorldCglib obj = new HelloWorldCglib();
        obj.setField("dispatcher");
        System.out.println("dispatcher after");
        return obj;
    }
}

public class HelloWorldCglibLazyLoader implements LazyLoader {
    @Override
    public Object loadObject() throws Exception {
        System.out.println("lazy loader before");
        HelloWorldCglib obj = new HelloWorldCglib();
        obj.setField("lazy loader");
        System.out.println("lazy loader after");
        return obj;
    }
}

public class ReflectApplication {
    public static void main(String[] args) throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(HelloWorldCglib.class);
        enhancer.setCallback(new HelloWorldCglibLazyLoader());
        HelloWorldCglib lazyProxy = (HelloWorldCglib) enhancer.create();
        lazyProxy.setField("origin lazy");
        System.out.println(lazyProxy.getField());
        System.out.println("===================");
        lazyProxy.setField("origin 2 lazy");
        System.out.println(lazyProxy.getField());
        System.out.println("-------------------");
        
        Enhancer enhancer2 = new Enhancer();
        enhancer2.setSuperclass(HelloWorldCglib.class);
        enhancer2.setCallback(new HelloWorldCglibDispatch());
        HelloWorldCglib dispatcherProxy = (HelloWorldCglib) enhancer2.create();
        dispatcherProxy.setField("origin dispatcher");
        System.out.println(dispatcherProxy.getField());
        System.out.println("===================");
        dispatcherProxy.setField("origin 2 dispatcher");
        System.out.println(dispatcherProxy.getField());

    }
}

// 结果
lazy loader before
lazy loader after
origin lazy
===================
origin 2 lazy
-------------------
dispatcher before
dispatcher after
dispatcher before
dispatcher after
dispatcher
===================
dispatcher before
dispatcher after
dispatcher before
dispatcher after
dispatcher
View Code

 

posted @ 2022-10-15 16:30  黎明的星海  阅读(49)  评论(0编辑  收藏  举报