AOP 底层使用动态代理,分为两种情况:
Spring 一般基于 AspectJ 实现 AOP 操作,可基于 xml 实现,也可基于注解实现(常用)
语法结构:execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))
// 例一:对 Book 类的 add 方法进行增强,*表示任意修饰符(public,private...),返回类型可以省略
execution(* com.dao.Book.add(..))
// 例二:对 Book 类所有方法进行增强
execution(* com.dao.Book.*(..))
// 例三:对 dao 包里所有的所有方法进行增强
execution(* com.dao.*.*(..))
(1)在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.aop.anno"/>
</beans>
(2)使用注解加载类的 bean,并在增强类上添加 @Aspect 注解
package com.aop.anno;
import org.springframework.stereotype.Component;
// 被增强的类
@Component
public class User {
void add() {
System.out.println("增加了一个用户");
}
}
package com.aop.anno;
import org.springframework.stereotype.Component;
// 增强类
@Component
@Aspect // 生成代理对象
public class UserProxy {
@Before("execution(* com.aop.anno.User.add(..))")
public void before() {
System.out.println("before...");
}
// 最终通知,发生异常也执行
@After("execution(* com.aop.anno.User.add(..))")
public void after() {
System.out.println("after...");
}
// 后置(返回)通知,触发 afterThrowing 不执行
@AfterReturning("execution(* com.aop.anno.User.add(..))")
public void afterReturning() {
System.out.println("afterReturning...");
}
@Around("execution(* com.aop.anno.User.add(..))")
public void around(ProceedingJoinPoint pj) throw Throwable {
System.out.println("环绕前");
pj.process();
// try {
// pj.proceed();
// } catch (Throwable throwable) {
// throwable.printStackTrace();
// }
System.out.println("环绕后");
}
// 有异常才执行
@AfterThrowing("execution(* com.aop.anno.User.add(..))")
public void afterThrowing() {
System.out.println("afterThrowing...");
}
}
(3) 在 spring 配置文件中开启生成代理对象
<aop:aspectj-autoproxy/>
(4) 测试
public void text() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
User user = context.getBean("user", User.class);
user.add(); // 先输出 before...,再输出 hhh
}
执行结果:
环绕前
before......
增加了一个用户
环绕后
after........
afterReturning
如果在 add 方法中引发了异常,则执行结果为:
环绕前
before......
after........
afterThrowing......
注意如果在 around 方法中异常没有被抛出而是在方法体内被处理,则不会执行 afterThrowing 方法,此时执行结果为:
环绕前
before......
环绕后
after........
afterReturning
如果将上面的 around 方法注释掉,则引发异常后结果为:
before......
after........
afterThrowing......
@Pointcut("execution(* com.kuang.service.UserServiceImpl.*(..))")
public void pointdemo() {}
@Before("pointdemo()")
public void before() {
System.out.println("before......");
}
@After("pointdemo()")
public void after() {
System.out.println("after........");
}
在增强类上添加 Order(int v) 注解,v 越小优先级越高
创建配置类,不需要 xml 配置文件
@Configuration
@Component(basePackages = {"com.pojo"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop{}
使用和 IOC 的完全注解开发一样
<!--增强类-->
<bean id="diy" class="com.kuang.diy.DiyPointCut"/>
<aop:config>
<!-- 切入点 -->
<aop:pointcut id="point" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
<!-- 自定义切面,ref 为增强类 -->
<aop:aspect ref="diy">
<!-- 通知 -->
<aop:before method="before111" pointcut-ref="point"/>
<aop:after method="after111" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
原文:https://www.cnblogs.com/214txdy/p/15024961.html