一、静态代理。(在代理类构造方法中引用被代理类的对象)
被代理类接口
public interface Subject {
public void say();
}
被代理类
public class RealSubject implements Subject {
@Override
public void say() {
System.out.println("Hello Real Subject .....");
}
}
代理类
public class ProxySubject implements Subject {
private Subject sub;
@Override
public void say() {
sub.say();
}
public ProxySubject(Object obj){
this.sub = (Subject) obj;
}
}
测试类
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
Subject sub = new RealSubject();
sub.say();
Subject proxySub = (Subject)new ProxySubject(new RealSubject());
proxySub.say();
}
}
【注】我觉得吧,既然创建了RealSubject的对象,代理也就没什么意义吧。直接sub.say()不就完了吗。我觉得在ProxySubject里面用发射可能更好理解。
二、动态代理(BeanUtil)
(采用 JDK 的反射机制和动态代理生成了代理对象 , 并进行方法拦截 )
被代理类接口
package DongTai.BeanUtil;
public interface IAction {
public void doProcess();
}
被代理类
package DongTai.BeanUtil;
public class ActionImpl implements IAction {
@Override
public void doProcess() {
}
}
代理工厂
package DongTai.BeanUtil;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory implements InvocationHandler{
private Object targetObject ;
public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
Class cl = Proxy.getProxyClass(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces());
System.out.println(cl.getName());
return Proxy.newProxyInstance (targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this );
/*Class cl = getProxyClass(loader, interfaces);//返回一个interfaces的接口实现类
Constructor cons = cl.getConstructor(constructorParams);
//返回实现类里面的一个构造方法
// constructorParams的定义为:private final static Class[] constructorParams = {InvocationHandler.class};
return (Object)cons.newInstance(new Object[]{h});
//执行这个构造方法返回一个对象(里面肯定执行了h.invoke(....))*/
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
IAction action = (IAction) targetObject ;
Object result = null ;
try {
System. out .println( " 检查权限 ......." );
//反射
result = method.invoke(action, args);
System. out .println( " 检查权限完毕 ...." );
} catch (Exception e) {
System. out .println( " 运行时发生异常 ..." );
} finally {
System. out .println( " 调用结束 ..." );
}
return result;
}
}
【注】通过打印发现Class cl 的名称是$Proxy0 ,看不懂这里。大致理解是第一步返回一个接口实现类,第二步是获取其中的一个构造方法,第三步是执行构造方法(里面调用当前代理工厂中的invoke方法,这个invoke方法里面通过反射执行被代理类中的方法.....也就是上面我的疑问)
测试类
package DongTai.BeanUtil;
public class App {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory();
IAction action = (IAction)factory.createProxyInstance( new ActionImpl());
action.doProcess ();
}
}
三、动态代理(cglib)
(BeanUtil 对于没有实现接口的类不能采用以上方法产生代理类,此时可以用 cglib 的 jar 包,这里采用 cglib-nodep-2.1_3.jar )
代理工厂
package DongTai.Cglib;
import java.lang.reflect.Method;
public class CglibProxyFactory implements MethodInterceptor{
private Object targetObject ;
public Object createProxyInstance(Object targetObject) {
this . targetObject = targetObject;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetObject.getClass());
enhancer.setCallback( this );
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodproxy) throws Throwable {
Object result = null ;
try {
System. out .println( " 检查权限 ......." );
result = methodproxy.invoke( targetObject , args);
System. out .println( " 检查权限完毕 ...." );
} catch (Exception e) {
System. out .println( " 运行时发生异常 ..." );
} finally {
System. out .println( " 调用结束 ..." );
}
return result;
}
}
测试类
package DongTai.Cglib;
public class App {
public static void main(String[] args) {
CglibProxyFactory factory = new CglibProxyFactory();
ActionImpl action = (ActionImpl)factory.createProxyInstance( new ActionImpl());
action.doProcess();
}
}
【注】是不是有点熟悉了?我们在Struts2框架中定义的拦截器也是使用了MethodInterceptor
Spring当中提供了两种实例化方案: BeanUtils 和 Cglib 方式。BeanUtils实现机制是通过Java的反射机制,Cglib是一个第三方类库采用的是一种字节码加强方式机制。 Spring中采用的默认实例化策略是Cglib。