spring AOP详解二

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就是需要代理实例实现的接口列表。

posted on 2014-05-12 15:50  锟斤拷锟斤拷  阅读(202)  评论(0编辑  收藏  举报

导航