Spring AOP详细介绍(一)

一直有个想法,想写一些文章记录下工作和学习中的一些心得。最近刚好在回顾Spring方面的东西,Spring Aop是Spring框架中很重要的一个功能。下面介绍下AOP(面向切面)。
AOP称为面向切面编程,在程序开发中用来解决一些系统层面上的问题,比如日志,事务,权限等。

一 AOP的基本概念

(1) Aspect(切面):通常是一个类,里面可以定义切入点和通知
(2) JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
(3) Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
(4) Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
(5) Target Object(目标对象):被一个或者多个切面所通知的对象
(6) Weaving(织入):把切面连接到其他的应用程序类或者对象上,并创建一个被通知的对象,分为:编译时织入、类加载时织入和执行时织入。

二 示例

  1. 例子1(脑残方法)
    先写一个接口 :
public interface Animal {
    public void run();
}

再写一个实现类:

public class AnimalImp implements Animal {
    public void run() {
        System.out.println("啪啪啪啪啪啪");
    }
    private void before(){
        System.out.println("before");
    }
    private void after(){
        System.out.println("after");
    }
}

在实现类中before()和after()方法都是硬编码,如果每个类都这么写也太傻了吧,代码review时等着被骂吧,哈哈。

  1. 例子2(静态代理)
    如果你刚刚学Java,可能还没学过什么设计模式,后面我也会写一些关于设计模式的总结。上面那种写法最简单地方法就是用静态代理模式,什么是代理呢,知道火车票代售点吧,代售点就是代理火车站买火车票的。说简单点老婆的代理就是小三,哈哈,扯远了。单独为AnimalImp写一个代理类:
public class AnimalProxy implements Animal {
    private AnimalImp animalImp;

    public AnimalProxy(AnimalImp animalImp) {
        this.animalImp = animalImp;
    }

    public void run() {
        before();
        animalImp.run();
        after();
    }
    private void before(){
        System.out.println("before");
    }
    private void after(){
        System.out.println("after");
    }
}

好吧,聪明的你肯定会觉得这样,每个类都写一个代理类,那么工作量不是剧增吗,有没有一种只写一个代理类的方法呢。有肯定是有的,那就要用到动态代理了。动态代理有JDK代理和CGLIB代理。

  1. 例子3(动态代理)
    3.1 JDK代理
    JDK代理是JDK提供的,JDK代理的目标类需要实现接口。
public class JDKDynamicProxy implements InvocationHandler {


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

    private Object target;

    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(target, args);
        after();
        return result;
    }

    private void before() {
        System.out.println("Before");
    }

    private void after() {
        System.out.println("After");
    }
}

代码跑一下:

public class JDKClient {
    public static void main(String[] args) {
        Animal animal = new JDKDynamicProxy(new AnimalImp()).getProxy();
        animal.run();
    }
}

3.2 CGLIB代理
JDK提供的动态代理只能代理接口,不能代理没有实现接口的类。我们可以使用开源的CGLIB类库来实现动态代理。

public class CGLIBDynamicProxy implements MethodInterceptor {
private static CGLIBDynamicProxy instance = new CGLIBDynamicProxy();

private CGLIBDynamicProxy() {
}
public static CGLIBDynamicProxy getInstance(){
    return  instance;
}
public <T> T getProxy(Class<T> cls){
    return (T) Enhancer.create(cls,this);
}

public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    before();
    Object result = methodProxy.invokeSuper(o,objects);
    after();
    return result;
}
private void before() {
    System.out.println("Before");
}

private void after() {
    System.out.println("After");
}
}
  1. 例子4(Spring AOP)
    当然Spring AOP是这篇文章的重点啦。要上班咯,先写这么点。待续。。。