代理的概念与作用
AOP面向切面编程
安全 事务 日志
StudentService ------|----------|------------|-------------
CourseService ------|----------|------------|-------------
MiscService ------|----------|------------|------------
用具体的程序代码描述交叉业务:
method1 method2 method3
{ { {
------------------------------------------------------切面
.... .... ......
------------------------------------------------------切面
} } }
交叉业务的编程问题即为面向方面的编程(Aspectoriented program ,简称AOP),AOP的目标就是要使交叉业务模块化。可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的,如下所示:
------------------------------------------------------切面
func1 func2 func3
{ { {
.... .... ......
} } }
------------------------------------------------------切面
使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。动态代理的实现
InvocationHandler接口:
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
参数说明:
Object proxy:指被代理的对象。
Method method:要调用的方法。
Object[] args:方法调用时所需要的参数。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ProxyTest1 {
public static void main(String[] args) {
final List list = new ArrayList();
Collection collection = (Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(), new Class[]{Collection.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
long startTime = System.currentTimeMillis();
Object obj = method.invoke(list, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName() + "操作所需的时间为:" + (endTime - startTime));
return obj;
}
});
//Collection collection = (Collection)getProxy(list, new MyAdvice());
collection.add("abc");
collection.add("xyz");
System.out.println("list的大小为:"+collection.size());
}
}
运行结果为:
add操作所需的时间为:0
size操作所需的时间为:0
list的大小为: 2
public class ProxyTest1 {
public static void main(String[] args) {
final List list = new ArrayList();
Collection collection = (Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(), new Class[]{Collection.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
long startTime = System.currentTimeMillis();
Object obj = method.invoke(list, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName() + "操作所需的时间为:" + (endTime - startTime));
return obj;
}
});
System.out.println(collection.getClass().getName());
}
}
按照刚才说的这个程序应该输出的是ArrayList的Class对象才对,但是程序实际运行结果却是:
动态代理的优化
import java.lang.reflect.Method;
public interface Advice {
public void beforeMethod(Method method);
public void afterMethod(Method method);
}
比如还是实现上面的计算程序执行的时间,在方法之前打印一句话,之后也打印一句话,接口的实现:
import java.lang.reflect.Method;
public class MyAdvice implements Advice {
private long start;
@Override
public void beforeMethod(Method method) {
start = System.currentTimeMillis();
System.out.println(method.getName() + " 操作执行之前");
}
@Override
public void afterMethod(Method method) {
long after = System.currentTimeMillis();
System.out.println(method.getName() + " 操作花费的时间为:" + (after - start)
+ "毫秒");
}
}
代这样生成代理类的方法就需要两个参数,一个是被代理的对象,还有一个是切面方法,也就是Advice对象。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ProxyTest1 {
public static void main(String[] args) {
final List list = new ArrayList();
Collection collection = (Collection)getProxy(list, new MyAdvice());
collection.add("abc");
}
public static Object getProxy(final Object target, final Advice advice){
Object proxy = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
advice.beforeMethod(method);
Object obj = method.invoke(target, args);
advice.afterMethod(method);
return obj;
}
});
return proxy;
}
}
执行结果为:
add 操作花费的时间为:0毫秒