再回首:如何实现Spring AOP -- 知识铺
再回首:如何实现Spring AOP?
引言
在本课程中,我们学习了Spring AOP的实现和应用。Spring AOP是Spring框架的核心组件之一,它允许我们以面向切面的方式处理那些与业务逻辑无关,但却是多个业务代码共同需要的功能,如日志记录、安全检查和事务管理等。通过这种方式,我们可以提高代码的可复用性、可维护性和可扩展性。
Spring AOP核心概念
Aspect(切面)
Aspect指的是横切逻辑(cross-cutting concerns),即那些跨越多个业务逻辑的功能。Aspect通过Join point、Advice和Pointcut来定义,并在运行时自动应用到不同的Join point上。
Join point(连接点)
Join point是程序执行过程中的一个点,如方法的调用或异常的处理。
Advice(通知)
Advice是Aspect在Join point上的具体行为,如在方法执行前后添加日志。
Pointcut(切点)
Pointcut用于定义哪些Join point会被Advice影响。
AOP的实现
Spring AOP的实现基于JDK动态代理,虽然实现简单,但效率不高且有限制。我们通过以下步骤实现AOP:
- 引入Java动态代理技术,探讨如何动态插入业务逻辑。
- 引入Spring的Interceptor和Advice概念,进一步抽取动态业务逻辑。
- 引入Spring的PointCut概念,定义Advice作用范围。
- 通过自动化机制自动生成动态代理,免除手工配置PointCut和Interceptor的工作。
思考题与参考答案
思考题17:动态代理
如果MiniSpring想扩展到支持Cglib,程序应该从哪里下手改造?
参考答案
改造可以从以下几个方面进行:
-
AopProxy接口:我们的动态代理包装在AopProxy这个接口中,对于JDK动态代理技术,使用了JdkDynamicAopProxy这个类来实现。对于Cglib技术,我们可以新增一个CglibAopProxy类进行实现。
-
ProxyFactoryBean:采用哪一种AOP Proxy可以由工厂方法决定,也就是在ProxyFactoryBean中所使用的aopProxyFactory。它在初始化的时候有个默认实现,即DefaultAopProxyFactory。我们可以将这个类的createAopProxy()方法改造一下,以支持Cglib。
|
|
根据某些条件决定使用JdkDynamicAopProxy还是CglibAopProxy,或者通过配置文件给一个属性来配置也可以。
18|拦截器 :如何在方法前后进行拦截?
思考题
如果我们希望beforeAdvice能在某种情况下阻止目标方法的调用,应该从哪里下手改造改造我们的程序?
参考答案
答案在MethodBeforeAdviceInterceptor 的实现中,看它的invoke方法。
|
|
这个方法先调用advice.before(),然后再调用目标方法。所以如果我们希望beforeAdvice能够阻止流程继续,可以将advice.before()接口改造成有一个boolean返回值,规定返回false则不调用mi.proceed()。
19|Pointcut :如何批量匹配代理方法?
思考题
我们现在实现的匹配规则是按照 *
模式串进行匹配,如果有不同的规则,应该如何改造呢?
参考答案
如果仍然按照名字来匹配,那就可以改造NameMatchMethodPointcut类,它现在的核心代码是:
|
|
功能扩展:增加正则表达式匹配方法
1. 现有实现
- 默认实现使用的是
PatternMatchUtils.simpleMatch()
,适用于简单的模式匹配。
2. 新增功能
-
增加一个名为
regExprMatch()
的方法,用于正则表达式匹配。 -
该方法将接收一个正则表达式字符串,并根据该表达式进行匹配校验。
3. 扩展匹配规则
-
如果需要超出名字匹配范围的匹配规则,可以增加一个
OtherMatchMethodPointcut
类和相应的Advisor
类。 -
用户需要自行实现这些类,并在配置文件中指定使用这个
Advisor
。
4. 配置文件指定
- 在配置文件中,可以指定使用自定义的
Advisor
,以便使用新的匹配规则。
5. 结构化和条理性
- 上述内容已经按照结构化和条理性重新编写,以确保清晰易懂。
|
|
20 | AutoProxyCreator:自动添加动态代理的实现
思考题
AOP在数据库事务处理中的应用 在面向切面编程(AOP)中,我们经常利用其特性来处理数据库事务。通过AOP,我们可以简化数据库事务的管理,使得代码更加简洁和易于维护。
参考答案
实现简单的事务处理
在数据库操作中,事务的处理通常涉及两个关键步骤:开启事务和提交事务。在不使用AOP的情况下,这通常需要在代码中显式地调用conn.setAutoCommit(false)
来开启事务,以及在操作完成后调用conn.commit()
来提交事务。通过AOP,我们可以将这些步骤封装成一个切面,自动在相应的方法执行前后进行调用。
使用MethodInterceptor实现
我们可以定义一个MethodInterceptor
,在其中实现事务的自动管理。以下是实现这一功能的步骤:
-
开启事务:在目标方法执行前,通过
conn.setAutoCommit(false)
禁用自动提交,从而开启一个事务。 -
执行业务逻辑:执行目标方法中定义的数据库操作。
-
提交或回滚事务:根据业务逻辑的执行结果,决定是调用
conn.commit()
提交事务,还是conn.rollback()
回滚事务。 通过这种方式,我们可以将事务管理的逻辑从业务代码中解耦出来,使得业务代码更加专注于业务逻辑本身,而事务管理则由AOP切面自动处理。
|
|
这个Interceptor拦截目标方法后添加事务处理逻辑,因此需要改造一下。
|
|
从代码里可以看到,这里需要一个conn,因此我们要设法将数据源信息注入到这里。
我们可以抽取出一个TranactionManager类,大体如下:
|
|
由这个transaction manager负责数据源以及开始和提交事务,然后将这个transaction manager作为一个Bean注入Interceptor,因此配置应该是这样的。
|
|
所以Interceptor最后应该改造成这个样子:
|
|
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/geek002/post/202410/%E5%86%8D%E5%9B%9E%E9%A6%96%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0Spring-AOP--%E7%9F%A5%E8%AF%86%E9%93%BA/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com