Spring中的AOP简单使用
1.AOP中相关术语
-
Join point: 连接点。潜在的那些方法。
-
Pointcut: 切点、切入点。其实就是一部分需要改变行为的连接点。
-
Target object: 目标对象。 需要被改变行为的对象。
-
AOP proxy: 代理对象。通过动态代理技术生成的那个对象。
-
Advice: 通知、增强。要改变方法行为的那部分逻辑。
-
Aspect: 切面。 切面 = 切点 + 通知。
-
Weaving: 织入。是将增强应用到切点中的过程。【往往体现为我们的配置】
-
Introduction: 【了解】引介增强。
说明文档spring-framework-reference:
链接:https://pan.baidu.com/s/1ztHMc5FBBNcT9XkGs-dWkQ
提取码:4m44
需要使用到的jar包
AspectJ(目的是在连接点中筛选出符合的切入点):
链接:https://pan.baidu.com/s/1YFMIimkO5Se-oMrGAwpwXw
提取码:5jrl
Spring-AOP
链接:https://pan.baidu.com/s/13OKSlRXy69vI0bwjRfh8OQ
提取码:ic16
以及其他的基础Spring包
2.基于XML配置的AOP
目录结构:
接口及实现类代码:
public interface AdminService {
void am1();
void am2();
void ah3();
}
public interface CustomerService {
void m1();
void m2();
void h3();
}
@Service
public class AdminServiceImpl implements AdminService {
@Override
public void am1() {
System.out.println("am1方法");
}
@Override
public void am2() {
System.out.println("am2方法");
}
@Override
public void ah3() {
System.out.println("ah3方法");
}
}
@Service
public class CustomerServiceImpl implements CustomerService {
@Override
public void m1() {
System.out.println("m1方法");
}
@Override
public void m2() {
System.out.println("m2方法");
}
@Override
public void h3() {
System.out.println("h3方法");
}
}
增强类
@Component
public class MyAdvice {
public void method(){
System.out.println("前置增强方法");
}
}
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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.example.service.impl ,com.example.advice"></context:component-scan>
<aop:config>
//指定哪些方法需要被增强
<aop:pointcut id="abc" expression="execution(void *())"></aop:pointcut>
<aop:aspect ref="myAdvice">
<aop:before method="method" pointcut-ref="abc"></aop:before>
</aop:aspect>
</aop:config>
</beans>
测试类
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:com/example/spring/spring-info.xml")
public class TestAop {
@Autowired
private AdminService adminService;
@Autowired
private CustomerService customerService;
@Test
public void test1(){
adminService.am2();
}
}
显示结果:
3.基于注解配置的AOP
目录结构
使用MyAdvice1作为增强类
@Component //目的:是将此类注册到Spring容器中
@Aspect //表示此类是一个切面
public class MyAdvice1 {
@Before("execution(void *())") //使用AspectJ表达式指定切入点
public void method(){
//前置逻辑
System.out.println("前置逻辑");
}
}
在xml中开启AOP功能
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.example.service.impl ,com.example.advice"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
测试代码
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:com/example/spring/spring-info.xml")
public class TestAop {
@Autowired
private AdminService adminService;
@Autowired
private CustomerService customerService;
@Test
public void test1(){
adminService.am2();
}
}
显示结果:
4.增强方式
上面的案例使用的是before的增强方式,对应还有:
<aop:before> 表示前置增强
@Before
<aop:after-throwing>
@AfterThrowing
当目标方法执行过程中,抛出异常的时候会执行这里的逻辑。 要想捕获异常类型,可以使用Exception类型的参数,同时使用throwing来绑定形参的名字。
<aop:after>
@After 目标方法执行后(不论是否抛出异常)
<aop:after-returning>
@AfterReturning 目标方法成功执行(有了返回值)后。
<aop:around> 【环绕:万金油】
@Around
5.环绕增强
增强类
@Component
@Aspect
public class MyAdvice1 {
@Around(value = "execution(void *())")
//该方法的参数类型必须是ProceedingJoinPoint,返回类型必须是Object
public Object method(ProceedingJoinPoint joinPoint){
Object[] args = joinPoint.getArgs();//调用目标方法时传递的实参
try {
System.out.println("前置逻辑");
joinPoint.proceed(args);//传递实参,调用方法
} catch (Throwable throwable) {
throwable.printStackTrace();//表示目标方法执行出现了异常
}
return null;
}
}
测试类
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:com/example/spring/spring-info.xml")
public class TestAop {
@Autowired
private AdminService adminService;
@Autowired
private CustomerService customerService;
@Test
public void test1(){
adminService.am2();
customerService.m1();
}
}
显示结果:
6.环绕汇总格式
/*
对于around环绕增强来说,参数类型必须是ProceedingJoinPoint 类型。返回值类型必须是Object类型。
*/
@Around(value = "execution(public * com.example..service.impl.*Impl.*(..))")
public Object m3(ProceedingJoinPoint point){
Object[] args = point.getArgs();//调用目标方法时传递的实参。
System.out.println("@Before这里写前置的功能......");
try {
Object result =null;
try {
result = point.proceed(args);//传递实参,调用目标方法
}finally {
System.out.println("是After的执行逻辑....");
}
System.out.println("是AfterReturning的执行逻辑.....");
return result;
} catch (Throwable throwable) {
// throwable.printStackTrace(); //表示目标方法执行过程中发生了异常。
System.out.println("相当于AfterThrowing"+throwable.getMessage());
}
return null;
}