Spring中有两种方式进行Bean的代理:
1。JDK 动态代理
JDK主要通过Proxy.newProxyInstance(Classloader, Interface[], InvocationHandler)方法,生成一个与目标类实现相同[b]接口[/b]的代理类,这也是为什么Spring中经常出现ClassCastException: $Proxy can not be cast to xxx. 因为生成的代理类并不是目标类的子类。
InvocationHandler接口主要包含一个invoke(Object, Method, Object[])方法。第一个参数为生成的代理类,第二个为要执行的方法,第三个为方法参数。
2。Cglib代理
JDK动态代理只能代理interface,对于没有实现任何接口的类,我们只能使用另一个Cglib代理。Cglib采用非常底层的字节码技术,可以为一个类创建子类。 Cglib的核心类是Enhancer, 它为目标类创建代理实例,并可以通过setCallBack设置回调类(CallBack),最常见的类为MethodInterceptor. 该类的主要方法为intercept(Object, Method, Object[], ProxyMethod)
interface
Bean
JDK代理-InvocationHandler
JDK代理- 测试
Cglib - MethodInterceptor
Cglib - 测试
1。JDK 动态代理
JDK主要通过Proxy.newProxyInstance(Classloader, Interface[], InvocationHandler)方法,生成一个与目标类实现相同[b]接口[/b]的代理类,这也是为什么Spring中经常出现ClassCastException: $Proxy can not be cast to xxx. 因为生成的代理类并不是目标类的子类。
InvocationHandler接口主要包含一个invoke(Object, Method, Object[])方法。第一个参数为生成的代理类,第二个为要执行的方法,第三个为方法参数。
2。Cglib代理
JDK动态代理只能代理interface,对于没有实现任何接口的类,我们只能使用另一个Cglib代理。Cglib采用非常底层的字节码技术,可以为一个类创建子类。 Cglib的核心类是Enhancer, 它为目标类创建代理实例,并可以通过setCallBack设置回调类(CallBack),最常见的类为MethodInterceptor. 该类的主要方法为intercept(Object, Method, Object[], ProxyMethod)
interface
package inter;
public interface PhoneInterface {
public void speak();
}
Bean
package Impl;
import inter.Phone;
import inter.PhoneInterface;
import javax.annotation.PostConstruct;
public class IPhone implements PhoneInterface{
public IPhone(int price, String name) {
super(price, name);
System.out.println("param construct");
}
public IPhone() {
System.out.println("default construct");
}
@Override
public void speak(){
System.out.println(this.getName()+" general speaks ");
}
}
JDK代理-InvocationHandler
package handler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MethodHandler implements InvocationHandler {
private Object target;
public MethodHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("call Method Name:"+method.getName());
System.out.println(proxy.getClass());
Object result = method.invoke(target, args);
return result;
}
}
JDK代理- 测试
package handler;
import inter.PhoneInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import Impl.IPhone;
public class TestJDKProxy {
public static void main(String arg[]){
IPhone iphone = new IPhone();
InvocationHandler handler = new MethodHandler(iphone);
PhoneInterface phone = (PhoneInterface)Proxy.newProxyInstance(iphone.getClass().getClassLoader(), IPhone.class.getInterfaces(), handler);
phone.speak();
}
}
Cglib - MethodInterceptor
package cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import Impl.IPhone;
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object createProxy(Class c){
enhancer.setSuperclass(c);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method method, Object[] arg2,
MethodProxy proxy) throws Throwable {
System.out.println("Method "+method.getName()+" begin");
Object result = proxy.invokeSuper(arg0, arg2);
System.out.println("Method "+method.getName()+" end");
return result;
}
}
Cglib - 测试
package cglib;
import Impl.IPhone;
public class TestCglibProxy {
public static void main(String args[]){
CglibProxy cgProxy = new CglibProxy();
IPhone phone = new IPhone();
// ApplicationContext context = new FileSystemXmlApplicationContext("/src/beans.xml");
//
// IPhone phone = (IPhone)context.getBean("iphone");
IPhone p = (IPhone)cgProxy.createProxy(phone.getClass());
p.speak();
}
}