spring学习总结013 --- AOP面向切面编程
AOP能够在应用程序指定位置、指定时机,植入指定功能,并且不影响原程序的功能;
最简单的而举例:在已有应用程序的所有方法调用前后分别添加日志;我们肯定不能修改程序,在每个方法前后添加日志,这样做工作量大,容易遗漏,更重要的是违背了“开闭原则”
AOP面向切面编程不是spring框架独有的,其他比较著名的框架是AspectJ;我们常说的spring AOP是spring整合和AspectJ,当然spring自身也实现了AOP,不过比较厚重(在spring事务中有应用)
一些基本概念
- 通知(Advice): AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。
- 连接点(join point): 连接点表示应用执行过程中能够插入切面的一个点,这个点可以是方法的调用、异常的抛出。在 Spring AOP 中,连接点总是方法的调用。
- 切点(PointCut): 可以插入增强处理的连接点。
- 切面(Aspect): 切面是通知和切点的结合。
- 引入(Introduction):引入允许我们向现有的类添加新的方法或者属性。
- 织入(Weaving): 将增强处理添加到目标对象中,并创建一个被增强的对象,这个过程就是织
这些概念比较抽象,需要在实际应用中理解
spring AOP实例(注解方式)
1、添加maven依赖:spring-aop、spring-aspects、spring-context
2、创建spring配置类
@Configuration // 声明为spring配置类 @ComponentScan(basePackages = {"com.demo"}) // 扫描com.demo包下的bean定义 @EnableAspectJAutoProxy // 为切面类创建代理, 植入增强 public class AopConfig { }
3、定义切面
@Slf4j @Aspect // 声明为切面 @Component public class LogAspect { // 定义切点及切点表达式, 即声明在哪些方法织入切面 @Pointcut("execution(public void com.demo.service.*.*(*))") public void pointcut() { } @Before("pointcut()") // 织入前置通知 public void before(JoinPoint joinPoint) { log.info("Before invoke method:{}", joinPoint.getSignature().getName()); } }
4、业务代码,spring会使用CGLIB为该类生成代理类
@Service public class AopService { public void func1(String name) { log.info("================Invoke func1, name:{}================", name); } }
5、测试代码
@Test public void test_cglib_proxy() { AopService aopService = applicationContext.getBean(AopService.class); aopService.func1("bale"); log.info("AopService class:{}", aopService.getClass().getName()); }
执行结果:
前面的业务代码采用CGLIB创建代理类,如果想采用JDK方式创建代理类,那么需要业务方法为接口实现类,举例如下:
接口:
public interface AopServiceIntf { public void printSomething(String name); }
实现类:
@Slf4j @Component public class AopServiceIntfImpl implements AopServiceIntf { @Override public void printSomething(String name) { log.info("=====================Invoke printSomething, name:{}====================", name); } }
测试类:
@Test public void test_jdk_proxy() { AopServiceIntf aopServiceIntf1 = (AopServiceIntf) applicationContext.getBean("aopServiceIntfImpl"); aopServiceIntf1.printSomething("bale1"); log.info("AopServiceIntf1 class:{}", aopServiceIntf1.getClass().getName()); }
执行结果:
spring AOP实例(XML配置方式)
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 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.demo" /> <aop:aspectj-autoproxy /> <bean class="com.demo.aop.LogXmlAspect" id="logXmlAspect" /> <aop:config> <aop:aspect id="logAspect" ref="logXmlAspect"> <aop:pointcut id="logPointcut" expression="execution(public void com.demo.service.*.*(*))"/> <aop:before method="before" pointcut-ref="logPointcut" /> </aop:aspect> </aop:config> </beans>
2、切面类
@Slf4j public class LogXmlAspect { public void before(JoinPoint joinPoint) { log.info("Before invoke method:{}", joinPoint.getSignature().getName()); } }
3、同样的测试类和业务类,执行结果:
指定代理方式
<aop:aspectj-autoproxy proxy-target-class="true" />
proxy-target-class="true"表示使用CGLIB代理方式
proxy-target-class="false"为默认值,如果委托类为接口实现类则使用JDK代理方式,否则采用CGLIB代理方式
心有猛虎,细嗅蔷薇
标签:
spring学习总结
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 开发的设计和重构,为开发效率服务
· 从零开始开发一个 MCP Server!
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时