动态代理:
这是一个常用设计模式。为什么需要代理,在现实生活中需要代理的情况很多,比如类似的助理职务等。在软件中,也有很多,比如代理服务器,在办公室上网一般都要经过代理服务器去访问外网,代理服务器中公司会做一些限制,比如一些购物网站不可以访问、流量限制等等。这就是代理的作用。在编程中,我们需要代理方法,这个方法可以帮我们做一些额外的工作比如日志、权限等。不同方法需要不同的代理方法,这就是动态代理。
有一个目标对象 RealObject,在代理模式中,我们再设计一个,接口和目标对象一致的代理对象Proxy,凡是需要调用目标对象的地方,都可以有代理对象来完成。
Spring AOP的核心就是动态代理,动态代理也是jdk的一个特性。通过JDK的动态代理特性,可以为任意的Java对象创建代理对象。
我们来看下在Java中是如何创建代理对象的。此对象要有一个接口。
在Java中提供了一个类Proxy,有一个生成代理对象的方法:
newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
调用这个方法,就可以生成一个代理对象,这个对象如何与目标对象的方法进行关联呢,是通过这个最后一个参数InvocationHandler h,如果
这个参数为空,会抛出异常。这个InvocationHander 是一个接口,有个invoke方法,使用时,我们需要创建一个他的实现类,比如RealHandler,然后将这个实现类传入到上述方法中。这个RealHandler中自然就需要实现这个invoke方法:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { doBefore(); method.invoke(target, args); doAfter() ; return null; }
就是在这个invoke方法中,加入代理所需要做的方法,然后通过method.invoke的回调调用原来的方法,method.invoke有两个参数,第一个是目标对象的实例,第二个是目标对象所调用方法的参数。这个method是所调用的那个方法。 Method和args都可以从InvocationHandler的invoke中取得,还需要一个目标对象的设置,这个需要我们手动设置:
private Object target;
public RealHandler(Object target){
super();
this.target = target;
}
下面将全部的代码贴出来:
package com.csair.aop;
public class RealObjectI implements RealObject{
@Override
public String realMethod(String s) {
System.out.println("target 打印S:"+s);
return null;
}
}
package com.csair.aop;
public interface RealObject {
public String realMethod(String s);
//如何在此方法 执行之前 做些操作,如果在方法返回之后做一些操作
}
package com.csair.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class RealHandler implements InvocationHandler {
private Object target;
public RealHandler(Object target){
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
doBefore();
method.invoke(target, args);
doAfter() ;
return null;
}
//其实我希望 在这个方法 可以获取参数
private void doBefore() {
System.out.println("before method invoke");
}
private void doAfter() {
System.out.println("after method invoke");
}
}
package com.csair.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class MainTest {
public static void main(String[] args) {
RealObject real=new RealObjectI();
InvocationHandler handler=new RealHandler(real);
//创建动态代理对象
RealObject proxy=(RealObject)Proxy.newProxyInstance(
real.getClass().getClassLoader(),
real.getClass().getInterfaces(),
handler);
proxy.realMethod("say :helloword");
}
}