JAVA动态代理和方法拦截(使用CGLib实现AOP)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA动态代理和方法拦截(使用CGLib实现AOP)相关的知识,希望对你有一定的参考价值。

经典的AOP一般通过Spring框架,实际上用CGLib更简便、更可控。

动态代理的实现非常优雅。

 

实体类:

public class SampleClass {

    public String MyFunction1(String input) {

        System.out.println("MyFunction1方法被调用:Hello:" + input);
        return "Hello:" + input;
    }

    public String MyFunction2(String input) {

        System.out.println("MyFunction2方法被调用:Hello:" + input);
        return "Hello:" + input;
    }
}

 

 

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Dispatcher;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.FixedValue;
import net.sf.cglib.proxy.LazyLoader;
import net.sf.cglib.proxy.NoOp;
import net.sf.cglib.proxy.ProxyRefDispatcher;

public class CgLibTest {
    
    private static String MyName = "";

    public static void main(String[] args) {

        MyName = "王昕";
        
        DoAOP();

        Enhancer enhancer1 = EnhancerNoOp();        
        SampleClass proxy = (SampleClass) enhancer1.create();
        String strOutput = proxy.MyFunction2("赵七");
        System.out.println("EnhancerNoOp:"+strOutput);
        
        Enhancer enhancer2 = EnhancerFixedValue();        
        SampleClass proxy2 = (SampleClass) enhancer2.create();
        String strOutput2 = proxy2.MyFunction2("赵七");
        System.out.println("EnhancerFixedValue:"+strOutput2);
        
    }

    private static void DoAOP() {
        MyInterceptor cglib = new MyInterceptor();
        SampleClass bookCglib = (SampleClass) cglib
                .getInstance(new SampleClass());
        bookCglib.MyFunction2("张三");
    }

    // 该回调将替代原类的方法实现
    private static Enhancer EnhancerFixedValue() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(SampleClass.class);
        
        enhancer.setCallback(new FixedValue() {
            @Override
            public Object loadObject() throws Exception {
                //返回 MyName 作为输入参数的;
                return new SampleClass().MyFunction2(MyName);
            }
        });
        return enhancer;
    }
    
    //执行原(Super)类方法
    private static Enhancer EnhancerNoOp() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(SampleClass.class);
        
        enhancer.setCallback(NoOp.INSTANCE);
        return enhancer;
    }
    
    //延迟加载
    private static Enhancer EnhancerLazyLoader() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(SampleClass.class);
        
        enhancer.setCallback(new LazyLoader() {
            @Override
            public Object loadObject() throws Exception {
                //return "回调后的返回值";
                return new SampleClass().MyFunction2(MyName);
            }
        });
        return enhancer;
    }
    
    private static Enhancer EnhancerProxyRefDispatcher(final String obj1) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(SampleClass.class);
        
        enhancer.setCallback(new ProxyRefDispatcher() {
            @Override
            public Object loadObject(Object obj2) throws Exception {
                return new SampleClass().MyFunction2(obj1 + (String)obj2);
            }
        });
        return enhancer;
    }


}

 

AOP拦截模拟类:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;


public class MyInterceptor implements MethodInterceptor {  
    private Object target;  
  
    public Object getInstance(Object target) {  
        this.target = target;  
        Enhancer enhancer = new Enhancer();  
        enhancer.setSuperclass(this.target.getClass());  
        // 回调方法  
        enhancer.setCallback(this);  
        // 创建代理对象  
        return enhancer.create();  
    }  
  
    @Override  
    // 回调方法  
    public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,  
            MethodProxy proxy) throws Throwable {  
        System.out.println("拦截前,做些事情");  
        proxy.invokeSuper(obj, args);  
        System.out.println("拦截后,再做些事情");  
        return null;  
   
    }  
  
}  

 

输出:

拦截前,做些事情
MyFunction2方法被调用:Hello:张三
拦截后,再做些事情
MyFunction2方法被调用:Hello:赵七
EnhancerNoOp:Hello:赵七
MyFunction2方法被调用:Hello:王昕
EnhancerFixedValue:Hello:王昕   

 

 

MethodDelegate

方法委托:  实现类似C#的委托。将方法调用绑定到某个接口的特定方法

    public void testMethodDelegate() throws Exception {
        SampleBean bean = new SampleBean();
        bean.setValue("Hello cglib!");
        BeanDelegate delegate = (BeanDelegate) MethodDelegate.create(bean,
                "getValue", BeanDelegate.class);
        assertEquals("Hello world!", delegate.getValueFromDelegate2());
    }

    public interface BeanDelegate {
        //String getValueFromDelegate1();
        String getValueFromDelegate2();
    }

 

BulkBean 

使用数组访问bean的访问器方法调用

    public void testBulkBean() throws Exception {
        BulkBean bulkBean = BulkBean.create(SampleBean.class,
                new String[] { "getValue" }, new String[] { "setValue" },
                new Class[] { String.class });
        SampleBean bean = new SampleBean();
        bean.setValue("Hello world!");
        assertEquals(1, bulkBean.getPropertyValues(bean).length);
        assertEquals("Hello world!", bulkBean.getPropertyValues(bean)[0]);
        bulkBean.setPropertyValues(bean, new Object[] { "Hello cglib!" });
        assertEquals("Hello cglib!", bean.getValue());
    }
public class SampleBean {
  private String value;
  public String getValue() {
    return value;
  }
  public void setValue(String value) {
    this.value = value;
  }
}

 

以上是关于JAVA动态代理和方法拦截(使用CGLib实现AOP)的主要内容,如果未能解决你的问题,请参考以下文章

java动态代理之CGLIB实现

CGlib和JDK动态代理

Cglib动态代理实现原理.md

JDK和CGLIB动态代理原理

CGlib代理技术

CGLib动态代理原理及实现