[Spring] Spring AOP编程理解
2017-09-06 12:53
375 查看
Spring AOP 编程理解
一、AOP的理解
最近在学习Spring,理解涉及到Spring的两大核心部分,一个是IOC(控制反转),另一个就是AOP(面向切面编程),今天主要讲一下什么是面向切面编程?在知乎上看到别人的回答,有句话觉得特别的有道理,“这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程”。
到底什么是AOP呢?就是把逻辑代码和处理繁琐事务的代码分离开,以便能够分离复杂度,让人在同一时间只用思考代码逻辑,或者琐碎事务,代码逻辑比如插入一条数据,那么琐碎事务就包括获取连接和关闭连接,事务开始,事务提交。
一般而言,我们将切入到指定类指定方法的代码片称为切面,而切入到哪些类、哪些方法则叫切入点,有了AOP,就可以将几个类共有的代码抽取到一个切片中,等到需要的时候再切入到对象中取,从而改变原有的行为。
举个例子:
先假设你有一段逻辑代码要写,在这段代码之前要写log,代码完成之后要写log,结局就是一大堆的log淹没了逻辑代码,而AOP的思想就是将非逻辑部分的代码抽离出来,只考虑逻辑代码就行了。
和AOP对应的是OOP,对于OOP,其为从横向上区分出一个个的类,而AOP从纵向上向对象中加入特定的代码。
Spring实现的AOP是代理模式(后面会介绍一下代理模式),给调用者实际使用的是已经加工过的对象。
二、动态代理
假设有这样几个类:ArithmeticCalculator.java
// ArithmeticCalculator接口 public interface ArithmeticCalculator { int add(int i, int j); int sub(int i, int j); int mul(int i, int j); int div(int i, int j); }
其有一个实现类:
ArithmeticCalculatorImpl.java
public class ArithmeticCalculatorImpl implements ArithmeticCalculator { public int add(int i, int j) { int result = i + j; return result; } public int sub(int i, int j) { int result = i - j; return result; } public int mul(int i, int j) { int result = i * j; return result; } public int div(int i, int j) { int result = i / j; return result; } }
若现在想实现这样的功能:在程序执行期间追踪正在发生的活动,此时代码将变为:
ArithmeticCalculatorLoggingImpl.java
public class ArithmeticCalculatorLoggingImpl implements ArithmeticCalculator { public int add(int i, int j) { System.out.println("The method add begins with[" + i + "," + j + "]"); int result = i + j; System.out.println("The method add ends with " + result); return result; } public int sub(int i, int j) { System.out.println("The method sub begins with[" + i + "," + j + "]"); int result = i - j; System.out.println("The method sub ends with " + result); return result; } public int mul(int i, int j) { System.out.println("The method mul begins with[" + i + "," + j + "]"); int result = i * j; System.out.println("The method mul ends with " + result); return result; } public int div(int i, int j) { System.out.println("The method div begins with[" + i + "," + j + "]"); int result = i / j; System.out.println("The method div ends with " + result); return result; } }
这样大量的log就淹没了业务逻辑代码,并且代码存在大量的重复,且如果要修改日志,此必须对每一处进行修改,显然这不是一种好的解决方法。
这时候动态代理就可以粉墨登场了!!!
ArithmeticCalculatorLoggingProxy.java
public class ArithmeticCalculatorLoggingProxy { // 要代理的对象 private ArithmeticCalculator target; public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) { this.target = target; } // 获取代码对象 public ArithmeticCalculator getLoggingProxy() { ArithmeticCalculator proxy = null; // 因为此时的代理对象proxy并不是像普通的对象一样是通过new得到的,此时java虚拟机有默认的类加载器,而现在这个对象是通过Proxy.newProxyInstance()方法得到的,因此必须告诉java虚拟机这个代理对象是由哪个类加载期进行加载 ClassLoader loader = target.getClass().getClassLoader(); // 实际的代理类使用的哪个接口,即代理类是什么类型 Class[] interfaces = new Class[]{ArithmeticCalculator.class}; // 当调用代理对象其中的方法时,该执行的代码 InvocationHandler h = new InvocationHandler() { /** * proxy: 正在返回的那个代理对象,一般情况下,在invoke方法中不使用该对象 * method:正在被调用的方法 * args: 调用方法时传入的参数 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); System.out.println("The method " + methodName + "begins with " + Arrays.asList(args)); Object result = method.invoke(target, args); System.out.println("The method " + methodName + "ends with " + result); return result; } }; proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h); return proxy; } }
而此时的main函数如下:
public class Main { public static void main(String[] args) { ArithmeticCalculator target = new ArithmeticCalculatorImpl(); ArithmeticCalculator proxy = new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy(); int result = proxy.add(1, 2); System.out.println("-->" + result); result = proxy.div(4, 2); System.out.println("-->" + result); } }
此时,ArithmeticCalculatorImpl中的函数全部都是业务逻辑,而与业务逻辑无关的代码均在代理中,若想修改业务逻辑无关代码,只需要在ArithmeticCalculatorLoggingProxy中进行修改即可,而无需修改ArithmeticCalculatorImpl中的代码!
相关文章推荐
- 简单模拟Spring AOP功能 (1) AOP编程思想的理解
- CGLIB实现AOP代理的测试类,与Spring分离,加深对面向切面编程的理解
- Spring面向切面编程AOP的个人理解
- 深入理解面向切面的编程AOP、AspectJ、Spring
- Spring入门(二)——理解spring的AOP编程
- 编程思想的理解(POP,OOP,SOA,AOP)
- Java+spring切面编程(aop)spring控制反转(ioc)+hibenrate对象关系映射(ORM
- SpringAOP编程实例
- 编程思想的理解(POP,OOP,SOA,AOP) x
- Spring AOP编程-aspectJ注解开发(@Pointcut声明切点)
- spring基于AspectJ的AOP编程
- java ssh spring aop 切面编程 操作日志
- 编程思想的理解(POP,OOP,SOA,AOP)
- Spring AOP: Spring之面向方面编程
- Spring AOP(创建切面理解)1
- 我所理解的Spring AOP的基本概念
- Spring_Aop编程_aop概述_通知介绍
- 学好Spring系列之理解AOP
- Spring容器AOP的理解
- Spring in Action 入门之面向切面编程AOP