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(脑残方法)
先写一个接口 :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时等着被骂吧,哈哈。
- 例子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代理。
- 例子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"); } }
- 例子4(Spring AOP)
当然Spring AOP是这篇文章的重点啦。要上班咯,先写这么点。待续。。。
- 例子2(静态代理)