什么是Spring AOP
Aspect Oriented Programming 面向切面编程
AOP的做法是将通用,与业务无关的功能抽象封装为切面类
切面可配置在目标方法执行前,后运行,真正做到即插即用
在不修改源码的情况下对程序行为进行修改
一个AOP的Demo
pom文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 7 <groupId>com.mingm.spring</groupId> 8 <artifactId>aop</artifactId> 9 <version>1.0-SNAPSHOT</version> 10 <repositories> 11 <repository> 12 <id>aliyun</id> 13 <name>aliyun</name> 14 <url>https://maven.aliyun.com/repository/public</url> 15 </repository> 16 </repositories> 17 <dependencies> 18 <dependency> 19 <groupId>org.springframework</groupId> 20 <artifactId>spring-context</artifactId> 21 <version>5.2.6.RELEASE</version> 22 </dependency> 23 <!--aspectjweaver是Spring AOP的底层依赖--> 24 <dependency> 25 <groupId>org.aspectj</groupId> 26 <artifactId>aspectjweaver</artifactId> 27 <version>1.9.5</version> 28 </dependency> 29 </dependencies> 30 </project>
applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns:context="http://www.springframework.org/schema/context" 4 xmlns:aop="http://www.springframework.org/schema/aop" 5 xmlns="http://www.springframework.org/schema/beans" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context.xsd 10 http://www.springframework.org/schema/aop 11 http://www.springframework.org/schema/aop/spring-aop.xsd"> 12 <bean id="userDao" class="com.mingm.spring.aop.dao.UserDao"/> 13 <bean id="employeeDao" class="com.mingm.spring.aop.dao.EmployeeDao"/> 14 <bean id="userService" class="com.mingm.spring.aop.service.UserService"> 15 <property name="userDao" ref="userDao"/> 16 </bean> 17 <bean id="employeeService" class="com.mingm.spring.aop.service.EmployeeService"> 18 <property name="employeeDao" ref="employeeDao"/> 19 </bean> 20 <!-- AOP配置 --> 21 <bean id="methodAspect" class="com.mingm.spring.aop.aspect.MethodAspect"></bean> 22 <aop:config> 23 <!-- PointCut 切点,使用execution表达式描述切面的作用范围 --> 24 <!-- execution(public * com.mingm..*.*(..)) 说明切面作用在com.mingm包下的所有类的所有方法上 --> 25 <!--<aop:pointcut id="pointcut" expression="execution(public * com.mingm..*.*(..))"></aop:pointcut>--> 26 <!--只对所有Service类生效--> 27 <aop:pointcut id="pointcut" expression="execution(* com.mingm..*Service.*(..))"></aop:pointcut> 28 <!--只对所有返回值为String类型方法生效--> 29 <!--<aop:pointcut id="pointcut" expression="execution(String com.mingm..*Service.*(..))"></aop:pointcut>--> 30 <!--对方法名进行约束 --> 31 <!--<aop:pointcut id="pointcut" expression="execution(* com.mingm..*Service.create*(..))"></aop:pointcut>--> 32 <!-- 对参数进行约束 --> 33 <!--<aop:pointcut id="pointcut" expression="execution(* com.mingm..*Service.*(String,*))"></aop:pointcut>--> 34 <!-- 定义切面类 --> 35 <aop:aspect ref="methodAspect"> 36 <!-- before通知(Advice),代表在目标方法运行前先执行methodAspect.printExecutionTime() --> 37 <aop:before method="printExecutionTime" pointcut-ref="pointcut"/> 38 <aop:after-returning method="doAfterReturning" returning="ret" pointcut-ref="pointcut"/> 39 <aop:after-throwing method="doAfterThrowing" throwing="th" pointcut-ref="pointcut"/> 40 <aop:after method="doAfter" pointcut-ref="pointcut"></aop:after> 41 </aop:aspect> 42 </aop:config> 43 </beans>
SpringApplication.java
1 package com.mingm.spring.aop; 2 3 import com.mingm.spring.aop.service.UserService; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 public class SpringApplication { 8 public static void main(String[] args) { 9 ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); 10 UserService userService = context.getBean("userService", UserService.class); 11 userService.createUser(); 12 userService.generateRandomPassword("MD5", 16); 13 } 14 }
MethodAspect.java
1 package com.mingm.spring.aop.aspect; 2 3 import org.aspectj.lang.JoinPoint; 4 5 import java.text.SimpleDateFormat; 6 import java.util.Date; 7 8 //切面类 9 public class MethodAspect { 10 //切面方法,用于扩展额外功能 11 //JoinPoint 连接点,通过连接点可以获取目标类/方法的信息 12 public void printExecutionTime(JoinPoint joinPoint){ 13 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); 14 String now = sdf.format(new Date()); 15 String className = joinPoint.getTarget().getClass().getName();//获取目标类的名称 16 String methodName = joinPoint.getSignature().getName();//获取目标方法名称 17 System.out.println("---->" + now + ":" + className + "." + methodName); 18 Object[] args = joinPoint.getArgs(); 19 System.out.println("---->参数个数:" + args.length); 20 for(Object arg:args){ 21 System.out.println("---->参数:" + arg); 22 } 23 } 24 25 public void doAfterReturning(JoinPoint joinPoint,Object ret){ 26 System.out.println("<----返回后通知:" + ret); 27 } 28 public void doAfterThrowing(JoinPoint joinPoint,Throwable th){ 29 System.out.println("<----异常通知:" + th.getMessage()); 30 } 31 public void doAfter(JoinPoint joinPoint){ 32 System.out.println("<----触发后置通知"); 33 } 34 }
Spring AOP 与AspectJ的关系
Eclipse AspectJ,一种基于Java平台的面向切面编程的语言
Spring AOP使用AspectJWeavear实现类与方法匹配
Spring AOP利用代理模式实现对象运行时功能扩展
Spring AOP相关概念
注解 | 说明 |
Aspect | 切面,具体的可插拔组件功能类,通常一个切面只实现一个通用功能 |
Target Class/Method | 目标类,目标方法,指真正要执行与业务相关的方法 |
PointCut | 切入点,使用execution表达式说明切面要作用在系统的哪些类上 |
JoinPoint | 连接点,切面运行过程中包含了目标类/方法元数据的对象 |
Adivice | 通知,说明具体的切面的执行时机,Spring包含五种不同类型通知 |