java動態代理和cglib動態代理

動態代理應用普遍,Spring,Struts等框架不少功能是經過動態代理,或者進一步封裝來實現的。java

常見的動態代理模式實現有Java API提供的動態代理和第三方開源類庫CGLIB動態代理。框架

Java API提供的動態代理是基於類反射實現的,用到的類有:ide

java.lang.reflect.InvocationHandler;測試

java.lang.reflect.Method;this

java.lang.reflect.Proxy;
spa

其實現是經過Proxy類的newProxyInstance()方法產生代理對象。自定義動態代理類須要實現InvocationHandler接口,該接口只有一個invoke()方法。代理


CGLIB是經過生成java 字節碼從而動態的產生代理對象,所以須要字節碼解析處理的依賴asm類庫,字節碼動態生成的代理對象其實是繼承了真實主題類的。這種實現方式須要導入cglib和asm的類庫。下面用到的例子是cglib-2.2.2.jar, asm-3.3.1.jar。cglib使用了MethodInterceptor,其中的方法是intercept(),這是攔截的概念,很容易就想到了Struts2的攔截器。code

比較之下,Java API提供的動態代理須要面向接口,產生代理對象,所以真實主題實現類必須實現了接口才能夠。而CGLIB不須要面向接口,能夠代理簡單類,但因爲動態代理對象是繼承真實主題實現類的,所以要求真實主題實現類不能是final的。orm

下面是實現的例子。對象

首先,爲了看到動態代理能夠根據不一樣類動態產生不一樣代理的效果,咱們新建兩個接口,及其實現類。

package leon.aj.dynproxy.target;  
  
public interface Hello {  
    public String sayHello(String name);  
}

實現類:

package leon.aj.dynproxy.target;  
  
public class HelloImpl implements Hello {  
    @Override  
    public String sayHello(String name) {  
        String s = "Hello, "+name;  
        System.out.println(this.getClass().getName()+"->"+s);  
        return s;  
    }  
}

另外一接口和實現類:

package leon.aj.dynproxy.target;  
  
public interface UserDao {  
    public boolean login(String username,String password);  
}
package leon.aj.dynproxy.target;  
  
public class UserDaoImpl implements UserDao {  
    @Override  
    public boolean login(String username, String password) {  
        String user = "("+username+","+password+")";  
        System.out.println(this.getClass().getName()+"-> processing login:"+user);  
        return true;  
    }  
}

應用Java API實現的動態代理類:

package leon.aj.dynproxy.java;  
  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
  
public class JavaDynProxy implements InvocationHandler{  
    private Object target;  
    public Object getProxyInstance(Object target){  
        this.target = target;  
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),   
                target.getClass().getInterfaces(), this);  
    }  
      
    @Override  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        Object result = null;  
        System.out.println("before target method...");  
        result = method.invoke(target, args);  
        System.out.println("after target method...");  
        return result;  
    }  
}

測試:

package leon.aj.dynproxy.java;  
  
import leon.aj.dynproxy.target.Hello;  
import leon.aj.dynproxy.target.HelloImpl;  
import leon.aj.dynproxy.target.UserDao;  
import leon.aj.dynproxy.target.UserDaoImpl;  
  
public class TestJavaProxy {  
    public static void main(String[] args) {  
        JavaDynProxy proxy = new JavaDynProxy();  
        Hello hello = (Hello)proxy.getProxyInstance(new HelloImpl());  
        String s = hello.sayHello("Leon");  
        System.out.println(s);  
          
        UserDao userDao = (UserDao) proxy.getProxyInstance(new UserDaoImpl());  
        userDao.login("Leon", "1234");  
        System.out.println(userDao.getClass().getName());  
    }  
}

下面是採用cglib實現的例子:

package leon.aj.dynproxy.cglib;  
  
import java.lang.reflect.Method;  
  
import net.sf.cglib.proxy.Enhancer;  
import net.sf.cglib.proxy.MethodInterceptor;  
import net.sf.cglib.proxy.MethodProxy;  
  
public class CglibProxy implements MethodInterceptor {  
    private Object target;    
      
    public Object getProxyInstance(Object target) {    
        this.target = target;  
        Enhancer enhancer = new Enhancer();    
        enhancer.setSuperclass(this.target.getClass());    
        enhancer.setCallback(this);  // call back method  
        return enhancer.create();  // create proxy instance  
    }    
      
    @Override  
    public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
        System.out.println("before target method...");  
        Object result = proxy.invokeSuper(target, args);  
        System.out.println("after target method...");  
        return result;  
    }  
}

測試類:

package leon.aj.dynproxy.cglib;  
  
import leon.aj.dynproxy.target.Hello;  
import leon.aj.dynproxy.target.HelloImpl;  
import leon.aj.dynproxy.target.UserDaoImpl;  
  
public class TestCiglib {  
    public static void main(String[] args) {  
        CglibProxy proxy = new CglibProxy();  
        Hello hello = (Hello) proxy.getProxyInstance(new HelloImpl());  
        System.out.println(hello.sayHello("Leon"));  
        UserDaoImpl userDao = (UserDaoImpl) proxy.getProxyInstance(new UserDaoImpl());  
        userDao.login("Leon", "1234");  
        System.out.println(userDao.getClass().getSuperclass());//看動態代理實例的父類  
    }  
}
相關文章
相關標籤/搜索