cglib动态代理

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

它只有两个核心API,MethodInterceptor.intercept拦截方法,Enhancer.create代理子类生成方法,所以不能代理final类。它速度快的原因是它内部维护了一套代理子类方法的索引表,寻址时会比较多。

public class Person {


public void testMethod(){


}


public static void main(String []args){

MethodInterceptor interceptor = new MethodInterceptor() {

@Override

public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

System.out.println("start");

Object proxy = methodProxy.invokeSuper(o, objects);//因为是创建子类的方式,所以此方法相当于调用了原方法

System.out.println("end");

return proxy;

}

};

Person person = (Person) Enhancer.create(Person.class, interceptor);

person.testMethod();

}

}

简单的cglib示例-代理方法

public class ConcreteClassNoInterface {
    public String methodA(String str){
        System.out.println("methodA:"+ str);
        return str;
    }
}
/**调用目标方法时,CGLIB会回调MethodInterceptor接口方法拦截,来实现你自己的代量逻辑
 * Created by liudong on 15/7/20.
 */
public class ConcreteClassInterceptor  implements MethodInterceptor{
    /**
     *
     * @param o cglib动态生成的代理类实现
     * @param method 上文中实体类中被代理方法的引用
     * @param arg 参数列表
     * @param methodProxy 生成的代理方法的引用
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
        System.out.println("before:"+ method);
        Object obj = methodProxy.invokeSuper(o, arg);//调用的是被代理类的相应的方法
        System.out.println("after:"+ method);
        return obj;
    }

    public static void main(String []args){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(ConcreteClassNoInterface.class);
        enhancer.setCallback(new ConcreteClassInterceptor());
        ConcreteClassNoInterface ccni = (ConcreteClassNoInterface)enhancer.create();//动态生成代理类
        ccni.methodA("ld");
    }/*:)output
    before:public java.lang.String com.shiro.spring.cglib.ConcreteClassNoInterface.methodA(java.lang.String)
    methodA:ld
    after:public java.lang.String com.shiro.spring.cglib.ConcreteClassNoInterface.methodA(java.lang.String)*/
}

回调过滤器-回调过滤

    在应用上述方法拦截后,可以对返回的结果进行二次过滤。

public class ConcreteClassNoInterface {
    public String methodA(String str){
        System.out.println("methodA:"+ str);
        return str;
    }

    public int methodB(int n){
        System.out.println("methodB:"+ n);
        return n+10;
    }

    public int methodC(int n){
        System.out.println("methodC:"+ n);
        return n+10;
    }
}
public class ConcreteClassFixedValue implements FixedValue {
    @Override
    public Object loadObject() throws Exception {
        System.out.println("ConcreteClassFixedValue loadObject...");
        Object object = 999;
        return object;
    }
}
public class ConcreteClassInterceptor  implements MethodInterceptor{
    @Override
    public Object intercept(Object o, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
        System.out.println("before:"+ method);
        Object obj = methodProxy.invokeSuper(o, arg);//调用的是被代理类的相应的方法
        System.out.println("after:"+ method);
        return obj;
    }
}
public class ConcreteClassCallbackFilter implements CallbackFilter {
    @Override
    public int accept(Method method) {
        if ("methodA".equals(method.getName())){
            return 0;//这个返回值对应main方法中callbacks数组的位置,调用方法时会用相应索引的拦截器拦截
        }else if("methodB".equals(method.getName())){
            return 1;
        }else if("methodC".equals(method.getName())){
            return 2;
        }
        return 1;
    }

    public static void main(String []args){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(ConcreteClassNoInterface.class);
        CallbackFilter filter = new ConcreteClassCallbackFilter();
        enhancer.setCallbackFilter(filter);

        Callback interceptor = new ConcreteClassInterceptor();
        Callback noOp = NoOp.INSTANCE;//什么也不做,代理类直接调用被代代理的方法不进行拦截
        Callback fixedValue = new ConcreteClassFixedValue();//锁定方法返回值而忽略被代理类的方法返回值
        Callback[] callbacks = new Callback[]{interceptor, noOp, fixedValue};
        enhancer.setCallbacks(callbacks);

        ConcreteClassNoInterface ccni = (ConcreteClassNoInterface)enhancer.create();//动态生成代理类

        System.out.println(ccni.methodA("ld")+"\n");
        System.out.println(ccni.methodB(2)+"\n");
        System.out.println(ccni.methodC(128));
    }
}/*:)output
before:public java.lang.String com.shiro.spring.cglib.ConcreteClassNoInterface.methodA(java.lang.String)
methodA:ld
after:public java.lang.String com.shiro.spring.cglib.ConcreteClassNoInterface.methodA(java.lang.String)
ld

methodB:2
12

ConcreteClassFixedValue loadObject...
999*/

延迟加载-LazyLoader接口

这引接口直接继承了Callback,也是callback类型中的一种。对需要延迟加载的对象添加代理,在获取该对象属性时先通过代理类回调方法进行对象初始化,在不需要加载该对象时,只要不去获取该对象内属性,该对象就不会被初始化了(在cglib中调用getter方法就会自动触发代理类回调)。

/**实体类
 * Created by liudong on 15/7/20.
 */
public class LoaderBean {
    private String loaderName;
    private int loaderValue;
    private PropertyBean propertyBean;//需要延迟加载的对象

    public LoaderBean(){
        this.loaderName = "loaderNameA";
        this.loaderValue = 123;
        this.propertyBean = createPropertyBean();//用ConcreteClassLazeLoader类完成代理类生成
    }

    protected PropertyBean createPropertyBean(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(PropertyBean.class);
        return (PropertyBean) enhancer.create(PropertyBean.class, new ConcreteClassLazeLoader());
    }

    public String getLoaderName() {
        return loaderName;
    }

    public void setLoaderName(String loaderName) {
        this.loaderName = loaderName;
    }

    public int getLoaderValue() {
        return loaderValue;
    }

    public void setLoaderValue(int loaderValue) {
        this.loaderValue = loaderValue;
    }

    public PropertyBean getPropertyBean() {
        return propertyBean;
    }

    public void setPropertyBean(PropertyBean propertyBean) {
        this.propertyBean = propertyBean;
    }

改进版本的延迟加载-Dispatcher

public class PropertyBean {
    private String name;
    private int value;

    public String getName() {
        return name;
    }

    public void setName(String name) {
         = name;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}
public class ConcreteClassLazeLoader implements LazyLoader {
    @Override
    public Object loadObject() throws Exception {
        System.out.println("lazy loadObject");
        PropertyBean bean = new PropertyBean();
        bean.setName("lazy loader name");
        bean.setValue(11);
        return bean;
    }

    public static void main(String []args){
        LoaderBean loaderBean = new LoaderBean();
        System.out.println(loaderBean.getLoaderName());
        System.out.println(loaderBean.getLoaderValue());

        PropertyBean bean = loaderBean.getPropertyBean();
        //触发代理类的回调方法loadObject
        System.out.println(bean.getName());
        System.out.println(bean.getValue());

        System.out.println("------");
        //再次访问量,就不会加载了
        System.out.println(bean.getName());
    }
}/*loaderNameA
123
lazy loadObject
lazy loader name
11
------
lazy loader name*/

改进版本的延迟加载-Dispatcher

   它和LazyLoader的区别在于:LazyLoader只在第一次访问延迟加载属性时触发代理类回调方法,而Dispatcher在每次访问延迟加载属性时触发代理类回调方法

public class LoaderBean {
    private String loaderName;
    private int loaderValue;
    private PropertyBean propertyBean;//需要延迟加载的对象

    public LoaderBean(){
        this.loaderName = "loaderNameA";
        this.loaderValue = 123;
        this.propertyBean = createPropertyBean();//用ConcreteClassLazeLoader类完成代理类生成
    }

    protected PropertyBean createPropertyBean(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(PropertyBean.class);
        return (PropertyBean) enhancer.create(PropertyBean.class, new ConcreteClassLazeDispatcher());
    }

    public String getLoaderName() {
        return loaderName;
    }

    public void setLoaderName(String loaderName) {
        this.loaderName = loaderName;
    }

    public int getLoaderValue() {
        return loaderValue;
    }

    public void setLoaderValue(int loaderValue) {
        this.loaderValue = loaderValue;
    }

    public PropertyBean getPropertyBean() {
        return propertyBean;
    }

    public void setPropertyBean(PropertyBean propertyBean) {
        this.propertyBean = propertyBean;
    }
}
public class PropertyBean {
    private String name;
    private int value;

    public String getName() {
        return name;
    }

    public void setName(String name) {
         = name;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}
public class ConcreteClassLazeDispatcher implements Dispatcher {
    @Override
    public Object loadObject() throws Exception {
        System.out.println("Dispatcher loadObject");
        PropertyBean bean = new PropertyBean();
        bean.setName("Dispatcher name");
        bean.setValue(11);
        return bean;
    }

    public static void main(String []args){
        LoaderBean loaderBean = new LoaderBean();
        System.out.println(loaderBean.getLoaderName());
        System.out.println(loaderBean.getLoaderValue());

        PropertyBean bean = loaderBean.getPropertyBean();
        //触发代理类的回调方法loadObject
        System.out.println(bean.getName());
        System.out.println(bean.getValue());

        System.out.println("------");
        //再次访问量,也同样会触发代理类的回调方法loadObject
        System.out.println(bean.getName());
    }
}/*loaderNameA
123
Dispatcher loadObject
Dispatcher name
Dispatcher loadObject
11
------
Dispatcher loadObject
Dispatcher name*/

接口生成器-InterfaceMaker

    它会动态生成一个接口,此接口包含指定类定义的所有方法

public class ConcreteClassNoInterface {
    public String methodA(String str){
        System.out.println("methodA:"+ str);
        return str;
    }

    public int methodB(int n){
        System.out.println("methodB:"+ n);
        return n+10;
    }

    public int methodC(int n){
        System.out.println("methodC:"+ n);
        return n+10;
    }
}
public class ConcreteClassInterfaceMaker {

    public static void main(String []args){
        InterfaceMaker interfaceMaker = new InterfaceMaker();
        interfaceMaker.add(ConcreteClassNoInterface.class);
        Class interfaceObj = interfaceMaker.create();
        System.out.println(interfaceObj.isInterface());
        System.out.println(interfaceObj.getName());

        Method []methods = interfaceObj.getMethods();
        for(Method method: methods){
            System.out.println(method.getName());
        } 
    }
}/*:)output
true
methodA
methodB
methodC*/