您的位置:首页 > 编程语言 > Java开发

spring AOP详解二

2014-05-12 15:50 225 查看
AOP实例(通过Proxy代理模式)

Spring AOP使用纯java实现,不需要专门的编译过程和类装载器,它在运行期间通过代理方式向目标类织入增强代码,它更侧重于提供一种和Spring IoC容器整合的AOP实现,在Spring中,我们可以无缝的将AOP,IoC,AspectJ整合在一起。

Spring AOP使用了两种代理机制:一种是基于JDK的动态代理,一种是基于CGLib的动态代理;

JDK1.3以后,java提供了动态代理技术,允许开发者在运行期间动态的创建接口的代理实例,JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler,其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态的将横切逻辑和业务逻辑编织在一起。

下面我们来看一个JDK动态代理的例子:

1.业务接口UserService.java

package spring.aop.demo1;

public interface UserService {
void removeUser(int userId);
}


2.横切逻辑代理监视代码PerformanceMonitor.java



package spring.aop.demo1;

public class MethodPerformance {

private long begin;

private long end;

private String serviceMethod;

public MethodPerformance(String serviceMethod) {
this.serviceMethod = serviceMethod;
this.begin = System.currentTimeMillis();
}

public void printPerformance() {
this.end = System.currentTimeMillis();
long elapse = end - begin;

System.out.println(serviceMethod + "花费" + elapse + "毫秒");
}

}






package spring.aop.demo1;

public class PerformanceMonitor {

// 通过一个ThreadLocal保存调用线程相关的性能监视信息
private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>();

// 启动对一目标方法的性能监视
public static void begin(String method) {
System.out.println("begin monitor...");
MethodPerformance mp = new MethodPerformance(method);
performanceRecord.set(mp);
}

public static void end() {
System.out.println("end monitor...");
MethodPerformance mp = performanceRecord.get();
mp.printPerformance();
}

}




3.横切逻辑代理代码PerformanceHandler.java



package spring.aop.demo1;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class PerformanceHandler implements InvocationHandler {

private Object target;

public PerformanceHandler(Object target) {
this.target = target;
}

@Override
public Object invoke(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
PerformanceMonitor.begin(target.getClass().getName() + "."
+ arg1.getName());
Object obj = arg1.invoke(target, arg2);// 通过反射机制调用目标对象的方法
PerformanceMonitor.end();
return obj;
}

}




首先,我们实现InvocationHandler接口,该接口定义了一个invoke方法,proxy最是最终生成的一个代理实例,一般不会用到,参数arg1是被代理目标实例的某个具体的方法,通过它可以发起目标实例方法的反射调用;参数arg2是通过被代理实例某一个方法的入参,在方法反射调用时候使用,通过代理将横切逻辑代码和业务类的代码编织到了一起。

我们在构造函数里通过target传入希望被代理的目标对象,将目标实例产地个method.inoke(),调用目标实例的方法。

4.通过Proxy结合PerformanceHandler创建UserService接口的代理实例:



package spring.aop.demo1;

import java.lang.reflect.Proxy;

public class UserServiceImpl implements UserService {

@Override
public void removeUser(int userId) {
System.out.println("模拟删除用户:" + userId);
try {
Thread.currentThread().sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static void main(String[] args) {
UserService userService = new UserServiceImpl();
// 将目标业务类和横切代码编织到一起
PerformanceHandler handler = new PerformanceHandler(userService);

// 根据编织了目标业务类逻辑和性能监视横切逻辑的InvocationHandler实例创建代理实例
UserService proxy = (UserService) Proxy.newProxyInstance(userService
.getClass().getClassLoader(), userService.getClass()
.getInterfaces(), handler);

proxy.removeUser(3);

}
}




输出:

begin monitor...
模拟删除用户:3
end monitor...
spring.aop.demo1.UserServiceImpl.removeUser花费203毫秒

说明:上面的代码完成业务类代码和横切代码的编制工作,并生成了代理实例,newProxyInstance方法的第一个参数为类加载器,第二个参数为目标类所实现的一组接口,第三个参数是整合了业务逻辑和横切逻辑的编织器对象。使用JDK代理模式有一个限制,即它只能为接口创建代理实例,这一点我们可以从Proxy.newProxyInstance的方法签名中就可以看的很清楚,第二个参数interfaces就是需要代理实例实现的接口列表。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: