java中是利用InvocationHandler 类实现代理,这是一个回调接口。
其中java代理并不神秘,说穿了就是使用一个和代理对象(也叫目标对象,为免混淆,以下称目标对象)实现了同样接口的一个类(这个类就叫代理类),用户实际是使用这个代理类来完成相关功能,而并不是使用所代理的目标对象本身。其原理是在代理类中有一个目标对象的成员,代理类调用目标成员的方法完成业务。因为这个特点,很容易在调用方法之前或之后来处理一些其它业务,这也就是AOP的实质。
闲话少说,看代码说明问题。不使用InvocationHandler ,我们可以自己这样实现一个简单代理类:
//定义一个接口:
interface Greet
{
void sayHello(String name);
void goodBye();
}
//实现这个接口:
class GreetImpl implements Greet
{
public void sayHello(String name)
{
System.out.println("Hello " + name);
}
public void goodBye()
{
System.out.println("Good bye.");
}
}
//实现一个代理类
public class SimpleProxy implements Greet
{
private Greet greet = null;
SimpleProxy(Greet greet)
{
this.greet = greet;
}
public void sayHello(String name)
{
System.out.println("--before method sayHello");
greet.sayHello(name);
System.out.println("--after method sayHello");
}
public void goodBye()
{
System.out.println("--before method goodBye");
greet.goodBye();
System.out.println("--after method goodBye");
}
/**
* @param args
*/
public static void main(String[] args)
{
Greet greet = new SimpleProxy(new GreetImpl());//生成代理
greet.sayHello("walter");
greet.goodBye();
}
}
再看看如果实现了InvocationHandler接口, 我们怎样实现代理。
还是要实现原来的Greet接口。 接口的实现还是GreetImpl。
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class DebugProxy implements java.lang.reflect.InvocationHandler
{
private Object obj;
public static Object newInstance(Object obj)
{
return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), new DebugProxy(obj));
}
private DebugProxy(Object obj)
{
//Greet接口的實現:GreetImpl
this.obj = obj;
}
//Method m:調用的方法
//Object[] args:方法要傳入的參數
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
{
Object result;
try
{
//自定義的處理
System.out.println("--before method " + m.getName());
//調用GreetImpl中方法
result = m.invoke(obj, args);
}
catch(InvocationTargetException e)
{
throw e.getTargetException();
}
catch(Exception e)
{
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}
finally
{
System.out.println("--after method " + m.getName());
}
return result;
}
/**
* @param args
*/
public static void main(String[] args)
{
Greet tmp = new GreetImpl();
Greet greet = (Greet) DebugProxy.newInstance(tmp);
//生成的greet和tmp有相同的hashCode
greet.sayHello("walter");
greet.goodBye();
}
}
//注:以上代码转摘自
//http://blog.csdn.net/aladdinty/archive/2009/03/11/3982007.aspx
可以看出,由于java的代理机制,被代理对象必须实现接口。
那如果被代理对象没有实现接口,就没有办法进行代理了吗?当然是可以的,我们可以让代理类继承自被代理对象,这样用户也可以通过父类(被代理类)获取代理对象的引用。Cglib就是这样的实现原理。Cglib中类似于InvocationHandler接口的是MethodInterceptor接口,需要覆写其intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy)方法,看看下面的基于cglib的代理实现:
//引入cglib库略过
public class CGlibProxyFactory implements MethodInterceptor{
privaet Object targetObject;
public Object createProxyIntance(Object targetObject){
this.targetObject = targetObject;
Enhnacer enhnacer = new Enhnacer();
////cglib实际上创建的代理是目标对象的一个子类,覆盖了父类中所有非final方法
enhnacer.setSuperclass(this.targetObject.getClass());
// setCallback(callback)设置回调对象 callback是实现方法拦截器的一个类
enhnacer.setCallback(this);
return enhnacer.create();
}
public Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable{
PersonServiceImpl bean = (PersonServiceImpl) this.targetObject;
Object result = null;
if(bean.getUser() != null){
result = methodProxy.invoke(targetObject, args);
}
return result;
}
}