步骤:
- 导入相应的依赖
- 开启注解扫描
- 编写代理接口
- 被代理接口实现类
- 编写切面类
- 测试
1. 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>org.example</groupId>
<artifactId>spring-11</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<!--导入AOP包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.aopalliance</groupId>
<artifactId>com.springsource.org.aopalliance</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>net.sourceforge.cglib</groupId>
<artifactId>com.springsource.net.sf.cglib</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
需要的依赖:
- com.springsource.net.sf.cglib-2.1.3.jar
- com.springsource.org.aopalliance-1.0.0.jar
- com.springsource.org.aspectj.weaver-1.9.6.RELEASE.jar
- spring-aspects-5.2.13.RELEASE
2.spring配置文件
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.qwy"/>
<!--开启注解的AOP实现-->
<aop:aspectj-autoproxy/>
</beans>
- content命名空间
- aop命名空间
3. POJO
package com.qwy.bean;
/**
* @author qwy
* @create 2021-04-24 9:46
**/
public class Users {
}
此类纯属为了模拟开发
4.代理接口
package com.qwy.servce;
import com.qwy.bean.Users;
/**
* @author qwy
* @create 2021-04-24 9:46
**/
public interface UsersService {
public void save(Users users);
public void update(Users users);
public void deleteById(Integer id);
public Users getUsersById(Integer id);
}
5. 代理接口实现类(被代理对象)
package com.qwy.servce.impl;
import com.qwy.bean.Users;
import com.qwy.servce.UsersService;
import org.springframework.stereotype.Service;
/**
* @author qwy
* @create 2021-04-24 9:47
**/
@Service("usersService")
public class UsersServiceImpl implements UsersService {
public void save(Users users) {
System.out.println("UsersServiceImpl.save");
}
public void update(Users users) {
System.out.println("UsersServiceImpl.update");
}
public void deleteById(Integer id) {
System.out.println("UsersServiceImpl.deleteById");
}
public Users getUsersById(Integer id) {
System.out.println("UsersServiceImpl.getUsersById");
return new Users();
}
}
只是为了演示AOP,跟业务无参,这里只做了打印,看效果。
- @Service :将被代理对象交给Spring容器管理。
6.切面类
package com.qwy.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author qwy
* @create 2021-04-24 9:29
**/
@Component
@Aspect
public class LogAspect {
@Pointcut("execution(* com.qwy.servce.impl.UsersServiceImpl.update(..))")
private void anyMethod(){}
@Before("anyMethod()")
public void beforeMethod(JoinPoint joinPoint){
//获取被代理对象的方法名
String name = joinPoint.getSignature().getName();
//获取被代理对象的参数列表
Object[] args = joinPoint.getArgs();
System.out.println("前置通知: 被代理对象的方法: " + name +" , 参数 :" + args);
}
@AfterReturning(value = "anyMethod()",returning = "result")
public void afterReturnMethod(JoinPoint joinPoint,Object result){
//获取被代理对象的方法名
String name = joinPoint.getSignature().getName();
//获取被代理对象的参数列表
Object[] args = joinPoint.getArgs();
System.out.println("返回通知: 被代理对象的方法: " + name +" , 参数 :" + args);
}
@AfterThrowing(value = "anyMethod()",throwing = "e")
public void afterThrowMethod(JoinPoint joinPoint, Exception e){
//获取被代理对象的方法名
String name = joinPoint.getSignature().getName();
//获取被代理对象的参数列表
Object[] args = joinPoint.getArgs();
System.out.println("异常通知: 被代理对象的方法: " + name +" , 参数 :" + args);
}
@After("anyMethod()")
public void after(JoinPoint joinPoint){
//获取被代理对象的方法名
String name = joinPoint.getSignature().getName();
//获取被代理对象的参数列表
Object[] args = joinPoint.getArgs();
System.out.println("后置通知: 被代理对象的方法: " + name +" , 参数 :" + args);
}
//@Around("anyMethod()")
public Object round(ProceedingJoinPoint joinPoint) throws Throwable {
Object proceed=null;
String name = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
try{
//前置通知
System.out.println("前置通知: 被代理对象的方法: " + name +" , 参数 :" + args);
proceed = joinPoint.proceed();
//返回通知
System.out.println("返回通知: 被代理对象的方法: " + name +" , 参数 :" + args);
}catch (Exception e){
System.out.println("异常通知: 被代理对象的方法: " + name +" , 参数 :" + args);
e.printStackTrace();
}finally {
System.out.println("后置通知: 被代理对象的方法: " + name +" , 参数 :" + args);
}
return proceed;
}
}
说明:
- @Component :切面必须是 IOC 中的 bean
- @Aspect :表名该类为切面类
- @Pointcut :定义切面表达式,格式:execution(访问修饰 返回值 类的全名称.方法名(参数列表))
- @Before(“anyMethod()”) :表示前置通知,接口的每一个实现类的每一个方法开始之前执行一段代码,anyMethod表示引用@Pointcut定 义的表达式,当然可以单独定义。
- @AfterReturning(value = “anyMethod()”,returning = “result”): 表示返回通知是可以访问到方法的返回值的!
- @AfterThrowing(value = “anyMethod()”,throwing = “e”):在目标方法出现异常时会执行的代码.可以访问到异常对象; 且可以指定在出现特定异常时在执行通知代码。
- @After(“anyMethod()”):在方法执行之后执行的代码. 无论该方法是否出现异常
- @Around(“anyMethod()”):环绕通知需要携带 ProceedingJoinPoint 类型的参数.环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是否执行目标方法.且环绕通知必须有返回值, 返回值即为目标方法的返回值。
7. 测试类
package com.qwy.test;
import com.qwy.bean.Users;
import com.qwy.servce.UsersService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author qwy
* @create 2021-04-24 9:49
**/
public class TestAnnotationAOP {
private ApplicationContext ac= new ClassPathXmlApplicationContext("applicationContext.xml");
@Test
public void test1(){
UsersService usersService = ac.getBean("usersService", UsersService.class);
usersService.save(new Users());
usersService.update(new Users());
usersService.deleteById(1);
usersService.getUsersById(1);
}
}
执行结果:
UsersServiceImpl.save
前置通知: 被代理对象的方法: update , 参数 :[Ljava.lang.Object;@3c947bc5
UsersServiceImpl.update
返回通知: 被代理对象的方法: update , 参数 :[Ljava.lang.Object;@3c947bc5
后置通知: 被代理对象的方法: update , 参数 :[Ljava.lang.Object;@3c947bc5
UsersServiceImpl.deleteById
UsersServiceImpl.getUsersById
需要演示的结果过多。这里没有分开演示,大家可以分别演示。