1. AOP 简介
AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, 面向对象编程) 的补充.
AOP 的主要编程对象是切面(aspect), 而切面模块化横切关注点.
在应用 AOP 编程时, 仍然需要定义公共功能, 但可以明确的定义这个功能在哪里, 以什么方式应用, 并且不必修改受影响的类. 这样一来横切关注点就被模块化到特殊的对象(切面)里.
AOP 的好处:
---每个事物逻辑位于一个位置, 代码不分散, 便于维护和升级
---业务模块更简洁, 只包含核心业务代码.
2. AOP的术语和图形表达
切面(Aspect): 横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象
通知(Advice): 切面必须要完成的工作
目标(Target): 被通知的对象
代理(Proxy): 向目标对象应用通知之后创建的对象
连接点(Joinpoint):程序执行的某个特定位置:如类某个方法调用前、调用后、方法抛出异常后等。连接点由两个信息确定:方法表示的程序执行点;相对点表示的方位。例如 ArithmethicCalculator#add() 方法执行前的连接点,执行点为 ArithmethicCalculator#add(); 方位为该方法执行前的位置
切点(pointcut):每个类都拥有多个连接点:例如 ArithmethicCalculator 的所有方法实际上都是连接点,即连接点是程序类中客观存在的事务。AOP 通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。切点和连接点不是一对一的关系,一个切点匹配多个连接点,切点通过 org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件。
3.在spring4中如何使用AOP?
①首先我们要做的还是先导入一系列架包。导入完以后右击buildpath引用下,如下:
②写一个含有+-*%方法的接口,并写好他的实现类代码如下:
1.ArithmeticCalculator(接口)
package com.icss.spring.aopimpl; 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); }2.实现类,记得在实现类上面加上注解交给spring来管理
package com.icss.spring.aopimpl; import org.springframework.stereotype.Component; @Component("arithmeticCalculator") 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; } }3.先写一个main函数来测试下,此时直接输出result=12,结果前后并没有打印日志记录,我们需要做的就是要让结果前后显示日志记录。
package com.icss.spring.aopimpl; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { /** * @param args */ public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("aop.xml"); ArithmeticCalculator arithmeticCalculator= applicationContext.getBean(ArithmeticCalculator.class); int result = arithmeticCalculator.add(3, 9); System.out.println("result = "+result); } }
4.下面写一个loggingAspect日志切面(AOP编程)
package com.icss.spring.aopimpl; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Component @Aspect public class LoggingAspect { @Before("execution(public int com.icss.spring.aopimpl.ArithmeticCalculatorImpl.add(int , int ))") public void beforeMethod() { System.out.println("add方法执行之前打印出来"); } }
@Before("execution(public int com.icss.spring.aopimpl.ArithmeticCalculatorImpl.add(int , int ))")
这句话的意思就是我们需要明确的指出,这个方法需要在哪个方法执行之前,也可以使用通配符*,来让所有的方法之前都执行这个方法。
5.最后一步就是我们要配置下aop.xml文件,让他自动生成代理对象,执行main就ok了!特别注意xmls!!!上面的命名空间,千万不要忘了加!不然没用!!!!
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <context:component-scan base-package="com.icss.spring.aopimpl"></context:component-scan> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
6.我们想要的结果如下:(这里只写了前置通知的方法,后置通知大家可以自己试试!)
7.大家还可以在通知方法中声明一个类型为 joinpoint的参数,然后就能访问连接细节了,如方法名和参数值!代码如下: