本文来源于官方文档
Aspect Oriented Programming with Spring 面向切面编程
简介
- 面向切面编程(AOP)弥补面向对象编程(OOP)通过提供思考程序结构的另一种方式。在OOP中模块化的关键单元是类,而在AOP模块为单位的切面。面对关注点,如事务管理跨多个类型和对象切模块化。(这些关注经常被称为横切在AOP文学的关注。)
- Spring的一个关键组件就是AOP框架。虽然Spring IoC容器并不依赖于AOP,这意味着你不需要使用AOP,如果你不想,AOP补充Spring IoC容器提供了非常强大的中间件解决方案。
AOP概念
- 切面(Aspect): 横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象
- **连接点(Join point)**: 一个程序,在执行过程中的一个点,如方法的执行或异常的处理。在Spring AOP中,一个连接点总是 代表一个方法的执行。
- **通知(Advice): 在某个特定的一个方面动作的连接点。不同类型的建议包括“around”,“before”和“after”的建议。(advice 的类型将在下面讨论)。许多AOP框架,包括Spring,Model 中的Advice 作为拦截器,保持了拦截器链周围的连接点(Joinpoint)**。
- **切点(pointcut)**: 每个类都拥有多个连接点:例如 ArithmethicCalculator 的所有方法实际上都是连接点,即连接点是程序类中客观存在的事务。AOP 通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。切点和连接点不是一对一的关系,一个切点匹配多个连接点,切点通过 org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件
- **代理(AOP proxy)**: AOP框架,以实现Aspect契约(例如通知方法执行等等)创建的对象。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
advice的类型 :
- Before advice: 建议一个执行一个 Join point 之前,但它不具有防止执行流程的连接点(除非它抛出一个异常)的能力。
- After returning advice: 连接点(Join point)正常完成后,方法没有抛出异常后执行
- After throwing advice: advice抛出一个异常时执行。
- After (finally) advice: 结果都会执行,
- Around advice: 环绕通知, 围绕着方法执行
Spring 使用 AspectJ 注解 实现AOP 编程#####、
需导入 aop,aspects 相关jar包
AtithmeticCalculatorImpl.java实现类
package com.dream.apo.impl;
import org.springframework.stereotype.Component;
@Component("atithmeticCalculator1")
public class AtithmeticCalculatorImpl implements AtithmeticCalculator {
@Override
public int add(int i, int j) {
int result=i+j;
return result;
}
@Override
public int sub(int i, int j) {
int result=i-j;
return result;
}
@Override
public int mul(int i, int j) {
int result=i*j;
return result;
}
@Override
public int div(int i, int j) {
int result=i/j;
return result;
}
}
AOP实现代码 LoginAspect.java
package com.dream.apo.impl;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoginAspect {
@Before("execution(public int com.dream.apo.impl.AtithmeticCalculator.*(..) )")
public void beforeMethod(JoinPoint joinPoint){
String methodName=joinPoint.getSignature().getName();
Object []args=joinPoint.getArgs();
System.out.println("the method is "+methodName+"begin with "+Arrays.asList(args));
}
@After("execution(public int com.dream.apo.impl.AtithmeticCalculator.*(..) )")
public void after(JoinPoint joinPoint){
String methodName=joinPoint.getSignature().getName();
System.out.println("the method is "+methodName+" ends ");
}
@AfterReturning(value="execution(public int com.dream.apo.impl.AtithmeticCalculator.*(..) )",
returning="result")
public void afterReturning(JoinPoint joinPoint,Object result){
String methodName=joinPoint.getSignature().getName();
System.out.println("the method is "+methodName+" return ends "+result);
}
@AfterThrowing(value="execution(public int com.dream.apo.impl.AtithmeticCalculator.*(..) )",
throwing="ex")
public void afterThrowing(JoinPoint joinPoint,Exception ex){
String methodName=joinPoint.getSignature().getName();
System.out.println("the method is "+methodName+" occurs exception "+ex);
}
}
主方法
package com.dream.apo.impl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
AtithmeticCalculator act= (AtithmeticCalculator) ac.getBean("atithmeticCalculator1");
int result=act.add(3, 4);
System.out.println("result="+result);
result=act.div(6, 1);
System.out.println("result="+result);
}
}
applicationContext.xml 配置文件
<context:component-scan base-package="com.dream.apo.impl"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>