背景:记录aop的使用方式。aop相关术语概念自行了解清楚,以下仅贴示例。
spring 版本:5.0.8.RELEASE
相关jar包,参考一下附件pom.xml
注意:各advice的执行顺序参考
https://blog.csdn.net/LGHunter/article/details/85330500
DAO
bean
package com.spring.aop.dao.bean;
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
dao
package com.spring.aop.dao.dao;
import com.spring.aop.dao.bean.User;
public interface UserDao {
void add(User user);
}
daoimpl
package com.spring.aop.dao.impl;
import com.spring.aop.dao.bean.User;
import com.spring.aop.dao.dao.UserDao;
public class UserDaoImpl implements UserDao {
public void add(User user) {
System.out.println("添加用户,姓名:" + user.getName() + ",年龄:" + user.getAge());
}
}
Service
package com.spring.aop.service;
import com.spring.aop.dao.bean.User;
import com.spring.aop.dao.dao.UserDao;
public class UserService {
private UserDao userDao;
public void setUserService(UserDao userDao){
this.userDao = userDao;
}
public void addUser(User user) {
userDao.add(user);
}
}
controller
package com.spring.aop.controller;
import com.spring.aop.dao.bean.User;
import com.spring.aop.service.UserService;
public class UserController {
private UserService userService;
public UserController(UserService userService){
this.userService = userService;
}
public void addUser(User user) {
userService.addUser(user);
}
}
两个切面aspect
package com.spring.aop.advice;
import com.spring.aop.dao.bean.User;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 切面的工作 - 通知
*/
public class TestAdvice1 {
public void before(){
System.out.println("...TestAdvice1 before方法执行...");
}
//调用方法后的返回值 - 在方法切之后执行
public void returning(Object object){
System.out.println("###TestAdvice1方法返回之后的处理###" + (object==null ? "无数据" : object));
if (object instanceof User){
User user = (User) object;
user.setName("你的名字被修改了!");
System.out.println("TestAdvice1方法返回之后,处理完成");
}
}
public void after(){
System.out.println("...TestAdvice1after方法执行...");
}
//环绕,将被切的方法包围起来
public Object round(ProceedingJoinPoint point) throws Throwable {
System.out.println("******TestAdvice1 around1执行******");
Object o = point.proceed();//调用对应方法
System.out.println("******TestAdvice1 around2执行******");
return o;
}
public void throwing(Exception e) {
System.out.println("TestAdvice1方法出现异常时执行:"+e.getMessage());
}
}
package com.spring.aop.advice;
import com.spring.aop.dao.bean.User;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 切面的工作 - 通知
*/
public class TestAdvice2 {
public void before(){
System.out.println("...TestAdvice2 before方法执行...");
}
//调用方法后的返回值 - 在方法切之后执行
public void returning(Object object){
System.out.println("###TestAdvice2 方法返回之后的处理###" + (object==null ? "无数据" : object));
if (object instanceof User){
User user = (User) object;
user.setName("你的名字被修改了!");
System.out.println("TestAdvice2 方法返回之后,处理完成");
}
}
public void after(){
System.out.println("...TestAdvice2 after方法执行...");
}
//环绕,将被切的方法包围起来
public Object round(ProceedingJoinPoint point) throws Throwable {
System.out.println("******TestAdvice2 around1执行******");
Object o = point.proceed();//调用对应方法
System.out.println("******TestAdvice2 around2执行******");
return o;
}
public void throwing(Exception e) {
System.out.println("TestAdvice2方法出现异常时执行:"+e.getMessage());
}
}
test main
package com.spring.aop.main;
import com.spring.aop.controller.UserController;
import com.spring.aop.dao.bean.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("springaop.xml");
UserController userController =context.getBean("userController", UserController.class);
// UserDao userDao =context.getBean("userDaoImpl", UserDaoImpl.class);
User user=new User();
user.setAge(22);
user.setName("AOP Test");
userController.addUser(user);
}
}
aop xml的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
default-autowire="byName"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--设置byName的方式注入 - default-autowire="byName"-->
<!-- 设置bean,生成的bean交由spring容器保管,并分别使用构造器和set属性注入的方式注入 -->
<bean id="user" class="com.spring.aop.dao.bean.User">
<property name="age" value="18"/>
<property name="name" value="test"/>
</bean>
<bean id="userDaoImpl" class="com.spring.aop.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.spring.aop.service.UserService">
<property name="userService" ref="userDaoImpl"/>
</bean>
<bean id="userController" class="com.spring.aop.controller.UserController">
<constructor-arg ref="userService"/>
</bean>
<!-- 加入切面的bean -->
<bean id="testAdvice1" class="com.spring.aop.advice.TestAdvice1"/>
<bean id="testAdvice2" class="com.spring.aop.advice.TestAdvice2"/>
<!-- AOP相关设置 -->
<aop:config proxy-target-class="true">
<!-- 切面1 -->
<!--设置切点 - 在execution中进行相关设置-->
<aop:pointcut expression="execution(public * com.spring.aop.dao.impl.UserDaoImpl.*(..))" id="test1"/>
<aop:aspect ref="testAdvice1"> <!-- 指向相应的切面bean -->
<aop:before method="before" pointcut-ref="test1"/>
<aop:after method="after" pointcut-ref="test1"/>
<aop:after-returning method="returning" returning="object" pointcut-ref="test1"/>
<aop:after-throwing method="throwing" pointcut-ref="test1" throwing="e"/>
<aop:around method="round" pointcut-ref="test1"/>
</aop:aspect>
<!-- 切面2 -->
<aop:aspect ref="testAdvice2"><!-- 指向相应的切面bean -->
<aop:before method="before" pointcut-ref="test1"/>
<aop:after method="after" pointcut-ref="test1"/>
<aop:after-returning method="returning" returning="object" pointcut-ref="test1"/>
<aop:after-throwing method="throwing" pointcut-ref="test1" throwing="e"/>
<aop:around method="round" pointcut-ref="test1"/>
</aop:aspect>
</aop:config>
</beans>
执行结果:
...TestAdvice1 before方法执行...
******TestAdvice1 around1执行******
...TestAdvice2 before方法执行...
******TestAdvice2 around1执行******
添加用户,姓名:AOP Test,年龄:22
******TestAdvice2 around2执行******
###TestAdvice2 方法返回之后的处理###无数据
...TestAdvice2 after方法执行...
******TestAdvice1 around2执行******
###TestAdvice1方法返回之后的处理###无数据
...TestAdvice1after方法执行...
注意:相关aop的属性方法介绍可参考spring-aop.xsd文件。
附件pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>spring</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<scope>system</scope>
<systemPath>${project.basedir}/lib/aopalliance-1.0.jar</systemPath>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<scope>system</scope>
<systemPath>${project.basedir}/lib/aspectjweaver.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>