前段时间研究了Spring的AOP功能,觉得这个功能挺不错的,希望有机会可以用到自己的项目中。正好这个时候正在做的一个项目需要日志管理的功能,我不想和以前的做法一样,把日志功能的代码直接和业务逻辑的代码交织在一起,这样做不但不利于后期的维护,还可能影响系统的逻辑功能。舍弃了这种做法,AOP就可以派上用场了。
但实际使用的时候发现,AOP也不是书上讲的那么容易,期间遇到了很多问题需要解决。现在我把遇到的问题列举如下:
(1)项目中是使用了事物的,是通过spring实现的。刚开始没有考虑到系统要用AOP的时候,实现事务的功能是直接在spring容器中配置一个含有事务功能的抽象类,然后所有需要事务功能的类就继承这个类。现在涉及到AOP了,就需要拦截这些继承了事务功能的类的某些方法以便做日志记录。但这样做了,spring容器就起不来了,总是抱错说添加了日志拦截功能的类无法初始化。试了很多次都不行,无奈只好到网上去找解决问题的办法了。功夫不负有心人,找了一个下午,终于找到了一些有用的资料。有一篇文章上给出的问题和我现在遇到的问题是很相似的,但没有给出引起这种错误的具体原因,只是给出了解决问题的方法,按找这种方法试了,spring容器真的不再出现这种问题,顺利启动了,而且可以实现相应的功能。方法很简单,就是实现事务的方式由继承改成AOP代理就可以了,使用的是注解的方式。这样做管理事务就更加方便了,直接去掉代理就可以了,不用在每个bean里面去掉abstract属性这样麻烦。关键代码如下:
<!-- 事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
<tx:method name="up*" propagation="REQUIRED"/>
<tx:method name="import*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- aop代理设置 -->
<aop:config proxy-target-class="true">
<aop:pointcut id="txPointcut" expression="execution(* cn.ipanel.apps.cms..service.impl.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>
在这种情况下,日志记录的方式,我也用注解的方式实现了。通过这种方式,日志逻辑和业务逻辑就较好的分开了,方便日志代码的维护管理。
(2)但AOP注解的方式并不是任何方法都可以拦截,我在拦截Action中的方法是就遇到了这个问题,不管怎样试,拦截的方法都不起作用,且没有任何报错的信息。这让我非常苦恼,差点就要放弃了。无可奈何之下,带着这个问题请教了一个老同事,他看了几下配置文件后指出,struts中的Action没有实现接口,导致AOP无法发挥作用的关键。现在解决的办法有两个:一是为每个Action实现一个接口,然后就可以用这种方式了,但这样做觉得很别扭,且失去了接口的意义了,纯粹为了AOP 的情况下。基于以上考虑,放弃了这种方式。二是不用注解,采用Proxy的方式,可以顺利解决问题,但必须为每个Action类配置一个代理bean,很繁琐。在没有想到更好的方式之下,我就采用了第二中方法。通常记录日志都需要用户信息,在Action中就很容易得到这类信息,所以我才采取在Action层进行拦截的方式,虽然知道这种方式不好,但没办法。不然的话,只能为每个service方法传递一个user的对象了,但当初没有考虑到这个,现在实现起来也要做很多的修改,所以放弃了。配置文件中关键代码摘抄如下:
<bean name="/module/importXml"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="importAndExportXml" />
</property>
<property name="interceptorNames">
<value>importAndExportNodeXmlLoginfoAdvice</value>
</property>
<property name="proxyTargetClass" value="true"/>
</bean>
上面就是我在项目中应用AOP时遇到的主要问题,都解决了,希望可以对其他的人有帮助。
分享到:
相关推荐
Java进阶之SpringAOP应用共16页.pdf.zip
Spring AOP应用开源架构源码2021.pdf
使用Spring开发的AOP小程序,供学习使用
spring aop应用 spring aop应用 spring aop应用 spring aop应用 spring aop应用
主要是利用Spring AOP实现动态数据源,和数据缓存操作。
spring 采用aop 的实例
springaop:spring aop应用实例和源码解析
spring aop简单例子,入门学习的好资料
关于AOP注解前置通知、后置通知、返回通知、异常通知的注解注释及应用
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器...Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中
NULL 博文链接:https://fsh430623.iteye.com/blog/1226945
Spring AOP之5种增强方法应用范例 ,具体效果和过程看博文 http://blog.csdn.net/evankaka/article/details/45241863
一个基于@AspectJ的spring2.0 AOP应用实例,很小很简单,没有任何额外信息,最适合AOP入门学习。使用log4j打印信息。把项目直接import进myeclipse就可以使用啦......
java xml方式实现springaop编程,包含源码+jar包+解释
采用SpringAOP拦截Controller,Service实现操作日志管理,统一处理异常,登陆日志管理,是SpringAOP的应用实践。通过SpringAOP的处理,可以方便移植日志管理功能,是个不错的学习demo
NULL 博文链接:https://donlianli.iteye.com/blog/1900885
Context-support模块:提供了对第三方库嵌入Spring应用的集成支持,比如缓存(EhCache、Guava、JCache)、邮件服务(JavaMail)、任务调度(CommonJ、Quartz)和模板引擎(FreeMarker、JasperReports、速率)。 SpEL模块:...
第五章:Spring AOP 在 Spring Framework内部应用小马哥(mercyblitz)Spring AOP 在 Spring Framewor
AOP 采取横向抽取机制,取代了传统纵向继承体系的重复性代码,其应用主要体现在事务处理、日志管理、权限控制、异常处理等方面。 目前最流行的 AOP 框架有两个,分别为 Spring AOP 和 AspectJ。Spring AOP 使用纯 ...
Spring AOP配置事务方法,描述了spring的事务配置,方便开发应用和数据库的连接管理。