java 代理

一、JDK的动态代理类
Java代码
public interface IService {  
    boolean getService(String data);  


public interface IService {
boolean getService(String data);
}

Java代码
public class ServiceImpl implements IService {  
 
    public boolean getService(String data) {  
        if ("A".equals(data)) {  
            return true;  
        } else {  
            return false;  
        }  
    }  
 


public class ServiceImpl implements IService {

public boolean getService(String data) {
if ("A".equals(data)) {
return true;
} else {
return false;
}
}

}

Java代码
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
 
public class ServiceHandler implements InvocationHandler {  
    private Object delegateObj;  
 
    public ServiceHandler(Object delegateObj) {  
        this.delegateObj = delegateObj;  
    }  
 
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        System.out.println("Begin Transaction....");  
        boolean rtn = (Boolean) method.invoke(delegateObj, args);  
        System.out.println("End Transaction....");  
        return rtn;  
    }  
 


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ServiceHandler implements InvocationHandler {
private Object delegateObj;

public ServiceHandler(Object delegateObj) {
this.delegateObj = delegateObj;
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("Begin Transaction....");
boolean rtn = (Boolean) method.invoke(delegateObj, args);
System.out.println("End Transaction....");
return rtn;
}

}

Java代码
import java.lang.reflect.Proxy;  
 
public class Test {  
    public static void main(String args[]) {  
        ServiceImpl si = new ServiceImpl();  
 
        ServiceHandler sh = new ServiceHandler(si);  
 
        IService is = (IService) Proxy.newProxyInstance(si.getClass()  
                .getClassLoader(), si.getClass().getInterfaces(), sh);  
 
        is.getService("A");  
    }  


import java.lang.reflect.Proxy;

public class Test {
public static void main(String args[]) {
ServiceImpl si = new ServiceImpl();

ServiceHandler sh = new ServiceHandler(si);

IService is = (IService) Proxy.newProxyInstance(si.getClass()
.getClassLoader(), si.getClass().getInterfaces(), sh);

is.getService("A");
}
}

二、CGLIB的动态代理类






Figure 1: CGLIB Library and ASM Bytecode Framework图一显示了和CGLIB包和一些框架和语言的关系图。需要注意的是一些框架例如Spring AOP和Hibernate,它们为了满足需要经常同时使用JDK的动态代理和CGLIB包。Hiberater使用JDK的动态代理实现一个专门为WebShere应用服务器的事务管理适配器;Spring AOP,如果不强制使用CGLIB包,默认情况是使用JDK的动态代理来代理接口。



Java代码
public class Target {  
 
    public String execute() {  
        String message = "----------test()----------";  
        System.out.println(message);  
        return message;  
    }  


public class Target {

public String execute() {
String message = "----------test()----------";
System.out.println(message);
return message;
}
}

Java代码
import net.sf.cglib.proxy.MethodInterceptor;  
import net.sf.cglib.proxy.MethodProxy;  
import java.lang.reflect.Method;  
 
public class MyMethodInterceptor implements MethodInterceptor {  
 
    public Object intercept(Object object, Method method, Object[] args,  
            MethodProxy methodProxy) throws Throwable {  
        System.out.println(">>>MethodInterceptor start...");  
        Object result = methodProxy.invokeSuper(object, args);  
        System.out.println(">>>MethodInterceptor ending...");  
        return "hahahh";  
    }  


import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class MyMethodInterceptor implements MethodInterceptor {

public Object intercept(Object object, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
System.out.println(">>>MethodInterceptor start...");
Object result = methodProxy.invokeSuper(object, args);
System.out.println(">>>MethodInterceptor ending...");
return "hahahh";
}
}

Java代码
import net.sf.cglib.proxy.Enhancer;  
 
public class TestCglibProxy {  
    public static void main(String rags[]) {  
        Target target = new Target();  
        TestCglibProxy test = new TestCglibProxy();  
        Target proxyTarget = (Target) test.createProxy(Target.class);  
        String res = proxyTarget.execute();  
        System.out.println(res);  
    }  
 
    public Object createProxy(Class targetClass) {  
        Enhancer enhancer = new Enhancer();  
        enhancer.setSuperclass(targetClass);  
        enhancer.setCallback(new MyMethodInterceptor());  
        return enhancer.create();  
    }  


import net.sf.cglib.proxy.Enhancer;

public class TestCglibProxy {
public static void main(String rags[]) {
Target target = new Target();
TestCglibProxy test = new TestCglibProxy();
Target proxyTarget = (Target) test.createProxy(Target.class);
String res = proxyTarget.execute();
System.out.println(res);
}

public Object createProxy(Class targetClass) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(new MyMethodInterceptor());
return enhancer.create();
}
}

CGLIB包的基本代码很少,当学起来有一定的困难,主要是缺少文档,这也是开源软件的一个不足之处。目前CGLIB的版本是(2.1.2),主要由一下部分组成:

net.sf.cglib.core
Low-level bytecode manipulation classes; Most of them are related to ASM.
net.sf.cglib.transform
Classes for class file transformations at runtime or build time
net.sf.cglib.proxy
Classes for proxy creation and method interceptions
net.sf.cglib.reflect
Classes for a faster reflection and C#-style delegates
net.sf.cglib.util
Collection sorting utilities
net.sf.cglib.beans
JavaBean related utilities
大多时候,仅仅为了动态地创建代理,你仅需要使用到代理包中很少的一些API。

正如我们先前所讨论的,CGLIB包是在ASM之上的一个高级别的层。对代理那些没有实现接口的类非常有用。本质上,它是通过动态的生成一个子类去覆盖所要代理类的不是final的方法,并设置好callback,则原有类的每个方法调用就会转变成调用用户定义的拦截方法(interceptors),这比JDK动态代理方法快多了。



net.sf.cglib.proxy.MethodInterceptor能够满足任何的拦截(interception )需要,当对有些情况下可能过度。为了简化和提高性能,CGLIB包提供了一些专门的回调(callback)类型。例如:

net.sf.cglib.proxy.FixedValue
为提高性能,FixedValue回调对强制某一特别方法返回固定值是有用的。
net.sf.cglib.proxy.NoOp
NoOp回调把对方法调用直接委派到这个方法在父类中的实现。
net.sf.cglib.proxy.LazyLoader
当实际的对象需要延迟装载时,可以使用LazyLoader回调。一旦实际对象被装载,它将被每一个调用代理对象的方法使用。
net.sf.cglib.proxy.Dispatcher
Dispathcer回调和LazyLoader回调有相同的特点,不同的是,当代理方法被调用时,装载对象的方法也总要被调用。
net.sf.cglib.proxy.ProxyRefDispatcher
ProxyRefDispatcher回调和Dispatcher一样,不同的是,它可以把代理对象作为装载对象方法的一个参数传递。


代理类的所以方法经常会用到回调(callback),当是你也可以使用net.sf.cglib.proxy.CallbackFilter 有选择的对一些方法使用回调(callback),这种考虑周详的控制特性在JDK的动态代理中是没有的。在JDK代理中,对java.lang.reflect.InvocationHandler方法的调用对代理类的所以方法都有效。



Use a MethodInterceptor为了更好的使用代理,我们可以使用自己定义的MethodInterceptor类型回调(callback)来代替net.sf.cglib.proxy.NoOp回调。当对代理中所有方法的调用时,都会转向MethodInterceptor类型的拦截(intercept)方法,在拦截方法中再调用底层对象相应的方法。



Use a CallbackFilter




小结 GLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。 它底层使用字节码处理框架ASM。其原理是,生产一个要代理类的子类,子类覆盖要代理的类的所有不是final的方法。 它比使用java反射的JDK动态代理要快。通常情况下,你可以使用JDK的动态代理创建代理,当你要代理的类没有实现接口 或者为了更好的性能,CGLIB是一个好的选择。



你可能感兴趣的:(java,spring,jdk,AOP,.net)