Spring AOP实现方式
什么是AOP
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方
式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个
热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑
的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高
了开发的效率。
编程中,对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面。
实现方式一,主要实现Spring的api接口
applicationcontext.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:context="http://www.springframework.org/schema/context"
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/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:annotation-config/>
<!--方式一:使用原生Spring api接口-->
<bean id="log" class="com.liu.log.Log"/>
<bean id="AfterLog" class="com.liu.log.AfterLog"/>
<bean id="UserService" class="com.liu.service.UserServiceImpl"/>
<aop:config>
<!--切入点expression(表达式) execution(切入位置)-->
<aop:pointcut id="pointCut" expression="execution(* com.liu.service.UserServiceImpl.*(..))"/>
<!--执行环绕增强 哪个类, 切入到哪里-->
<aop:advisor advice-ref="log" pointcut-ref="pointCut"/>
<aop:advisor advice-ref="AfterLog" pointcut-ref="pointCut"/>
</aop:config>
</beans>
切入的内容
放切入点前
package com.liu.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class Log implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
//method:被调用的方法
//args:方法的参数
//target:方法调用的目标。可能为空
System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
放在切入点后
package com.liu.log;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class AfterLog implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
//returnValue 返回结果
//method: 被调用的方法
//args: 方法的参数
//target: 方法调用的目标。可能为空
System.out.println("执行完了"+method.getName()+"返回结果为"+returnValue);
}
}
一个接口一个实现
实现方式二 主要切面定义
增加放在切入点前后的方法
public class DiyPioncut {
public void before(){System.out.println("============切入点前================");}
public void after(){System.out.println("============切入点后================");}
}
配置applicationContext.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:context="http://www.springframework.org/schema/context"
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/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:annotation-config/>
<!--方式一:使用原生Spring api接口-->
<bean id="log" class="com.liu.log.Log"/>
<bean id="AfterLog" class="com.liu.log.AfterLog"/>
<bean id="UserService" class="com.liu.service.UserServiceImpl"/>
<bean id="diy" class="com.liu.DIY.DiyPioncut"/>
<!--方式二-->
<aop:config>
<aop:aspect id="diyPointcut" ref="diy">
<aop:pointcut id="point" expression="execution(* com.liu.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
</beans>
execution表达式
execution(* com.loongshawn.method.ces..*.*(..))
标识符 | 含义 |
---|---|
execution() | 表达式的主体 |
第一个“*”符号 | 表示返回值的类型任意 |
com.loongshawn.method.ces | AOP所切的服务的包名,即,需要进行横切的业务类 |
包名后面的“..” | 表示当前包及子包 |
第二个“*” | 表示类名,*即所有类 |
.*(..) | 表示任何方法名,括号表示参数,两个点表示任何参数类型 |
实现方式三 注解实现
xml文件开启注解扫描和支持注解
<!--开启注解支持-->
<aop:aspectj-autoproxy/>
<!--开启注解的支持-->
<context:component-scan base-package="com.liu.annnoPoincut"/>
<context:annotation-config/>
<bean id="log" class="com.liu.log.Log"/>
<bean id="AfterLog" class="com.liu.log.AfterLog"/>
<bean id="UserService" class="com.liu.service.UserServiceImpl"/>
<bean id="diy" class="com.liu.DIY.DiyPioncut"/>
切面类进行bean注册和切点确认
package com.liu.annnoPoincut;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
//标记这个类是一个切面
public class AnnoPoincut {
@Before("execution(* com.liu.service.UserServiceImpl.*(..))")
public void before() {
System.out.println("---------------执行前");
}
@After("execution(* com.liu.service.UserServiceImpl.*(..))")
public void after() {
System.out.println("---------------执行后");
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!