AOP
横切关注点: 日志
切面: 日志类 log
通知: log类的一个方法
目标: 指定的方法
代理:代理类
切入点,连接点 :在哪个地方执行
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" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 用到的都先注册上--> <bean id="userService" class="com.ljm.service.UserService_"/> <bean id="log" class="com.ljm.log.Log"/> <bean id="afterLog" class="com.ljm.log.Afterlog"/> <!-- 配置aop 需要导入aop 的约束--> <aop:config> <!-- 切入点[可多个](在哪里执行) expression是个表达式(格式固定) execution(要执行的位置) 任意访问修饰符 类名 方法名(.*) 参数(..)--> <aop:pointcut id="pointcut" expression="execution(* com.ljm.service.UserService_.*(..))"/> <aop:pointcut id="pointcut1" expression="execution(* com.ljm.service.UserService_.add(..))"/> <!-- 执行环绕增加 把log类切入到pointcut --> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut1"/> </aop:config> </beans>
接口(略)
实现类(略)
前置

public class Log implements MethodBeforeAdvice { @Override //method 需要执行目标对象的方法 //objects 相关参数 ==args //o 目标对象 ==target //自动调用 public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("前置 "+o.getClass().getName()+" 的 "+method.getName()+" 方法正在运行 "); } }
后置

public class Afterlog implements AfterReturningAdvice { @Override //returenValue 返回值 //method 需要执行目标对象的方法 //objects 相关参数 ==args //o 目标对象 ==target public void afterReturning(Object returenValue, Method method, Object[] objects, Object o1) throws Throwable { System.out.println(" after 执行了"+method.getName()+"方法 返回的结果为"+returenValue); } }
测试

public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //动态代理的是接口 UserService是接口 UserService userService = (UserService)context.getBean("userService"); userService.add(); userService.delete(); }
方法2:自定义类(视频推荐)
相对简单,但功能有限

public class DiyPointCut { public void before(){ System.out.println("=====前面执行==="); } public void after(){ System.out.println("=====后面执行==="); } }
XML相关

<bean id="diy" class="com.ljm.diy.DiyPointCut"/> <aop:config> <!-- 自定义切面 red需要引入的类--> <aop:aspect ref="diy"> <!-- 切入点--> <aop:pointcut id="point" expression="execution(* com.ljm.service.UserService_.*(..))"/> <!-- 通知 使用的方法是DiyPointCut中的的before 在切入点point处生效--> <aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config>
方法3:使用注解实现(调试代码不变)
在pom中导入依赖

<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.4</version> </dependency>
自定义相关类

@Aspect public class AnotationPointCut { @Before("execution(* com.ljm.service.UserService_.*(..))") public void before(){ System.out.println("方法执行前-注解实现,Before"); } @After("execution(* com.ljm.service.UserService_.*(..))") public void after(){ System.out.println("方法执行后-注解实现,After"); } //在环绕增强中,可以给个参数,代表获取处理的点 @Around("execution(* com.ljm.service.UserService_.*(..))") public void around(ProceedingJoinPoint jp){ System.out.println("环绕前"); // jp.getSignature(); System.out.println("签名=执行方法="+jp.getSignature()); try { Object proceed = jp.proceed(); //执行方法 } catch (Throwable throwable) { throwable.printStackTrace(); } System.out.println("环绕后"); } }
配置XML中

<!-- 方式三--> <bean id="diy01" class="com.ljm.diy.AnotationPointCut"/> <!-- 开启注解支持 JDK(默认false) true的话就用cglib实现 --> <aop:aspectj-autoproxy proxy-target-class="false"/>
执行顺序
AOP事务
<!-- 4.AOP横切事务支持--> <!-- 结合AOP实现事务的织入--> <!-- 配置事务通知--> <!-- 给某些方法(接口内的方法)配置事务+配置事务的传播特性propagation--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- <tx:method name="add" propagation="REQUIRED"/> 没有事务就添加一个事务--> <tx:method name="*" propagation="REQUIRED"/> <!-- *可以给全部方法配置事务 <tx:method name="*"/>--> </tx:attributes> </tx:advice> <!-- 配置事务切入--> <aop:config> <aop:pointcut id="txPointCut" expression="execution(* com.ljm.mapper.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config>
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术