切面和自定义注解的配合使用
2016-12-04 00:41
537 查看
一.概述
基于切面的编程(AOP)也许大家并不陌生,大家经常使用切面编程来解决事务问题。但是切面也有弊端,以笔者的经验看来,使用切面的不方便之处在于切面的精确度问题,我们很难把事务加到大量的指定类的指定方法上,本文就通过Spring AOP和自定义注解的配合使用来解决该问题。二.Spring AOP切面的使用和问题
使用:以事务为例,我们在搭建J2EE项目框架时,势必要处理事务。通常我们的做法是给service层的DML操作方法增加事务,具体代码如下:
// 对数据源进行管理 <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" /> <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception" /> <tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception" /> <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception" /> <tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception" /> <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception" /> <tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception" /> </tx:attributes> </tx:advice> <aop:config proxy-target-class="true"> <aop:advisor pointcut="execution(* com.etc..service.impl.*ServiceImpl.*(..))" advice-ref="txAdvice" /> </aop:config>
通过上面的配置,可以实现事务的处理,但是这个配置却非常不灵活,他限制了类必须在service层,其次,方法名必须以add、save、insert等开头,才能被切面管理到,如果不符合这些规则改怎么办呢?
新的需求:
在曾经的开发中遇到这样一个需求,系统中的部分业务方法在被调用到时,需要向log表插入日志,业务方法名没有规律,你不可能把所有的业务方法名都配置到上面,那么问题就来了,是否有一种语法可以在每个需要记录日志的方法中进行标识,让Spring AOP感知到,这就是下面要讲解的–自定义注解。
三.自定义注解
Annotation(注解)是JDK1.5以后引入的新特性,它是以‘@注解名’的形式在代码中存在的,它可以出现在类、方法和属性的上方,一旦被标记了注解,那么在编译期或运行期就可以动态的获取哪些类、哪些方法或属性被标记了注解,从而针对这些类、属性和方法进行对应的处理,正式因为这个特性,才可以解决我们上面提到的问题。如何自定义注解:
在了解自定义注解钱,需要了解元注解。元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
@Target
@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
@Retention
@Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。例如我们常见的@Override注解,他的@Retention就在source阶段,因为他仅仅是针对方法覆盖进行语法检查,只要符合了规则即可,在运行阶段就不需要了。
@Documented
@Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。
@Inherited
@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如
4000
果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
四.具体实现
注解代码:@Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface LogOperation { }
在代码中,我们定义了,改注解是方法级别,并且是在运行阶段有效的。
切面代码:
@Aspect @Component public class LogOperationAspect { Logger log = LoggerFactory.getLogger(LogOperationAspect.class); @Autowired ILogOperationService logOperationService; // 这里是关键点,把切面的连接点放在了我们的注解上 @Pointcut("@annotation(com.etc.annotation.LogOperation)") public void controllerAspect() { } // 在这里定义前置切面 @Before("controllerAspect()") public void beforeMethod(JoinPoint joinPoint) { // 这里执行保存日志的动作 this.saveLogOperation(joinPoint, StatusEnum.SUCCESS); } }
使用切面的代码:
// 只需要增加这样一个注解,就可以被切面管理 @LogOperation @ResponseBody @RequestMapping(value = "/get/{id}", method = RequestMethod.GET) public Map<String, Object> getDemo(@PathVariable Integer id, HttpServletRequest request, HttpServletResponse response) { DemoVO vo = this.demoService.selectById(id); return ResultMapper.convertSuccess(vo); }
五.总结
通过上面代码,我们可以看到,只要我们在期望记录日志的方法上增加@LogOperation注解,该方法的动作就会被记录进日志表,不管方法叫什么名字,类在什么位置,都可以轻松的解决,而且没有代码入侵,期望本篇博客对大家有所帮助。相关文章推荐
- 日志--切面(AOP)的使用,以及配合使用自定义注解
- 切面和自定义注解的配合使用
- 利用自定义注解来配合使用SpirngMVC拦截器
- SpringAOP使用入门,如何对自定义的注解进行切面编程
- 解析动态代理模式与跟自定义注解配合使用以及事务注解原理
- Java自定义注解 和 springMVC拦截器 配合使用记录系统操作日志的案例
- 使用自定义注解和切面记录系统日志
- 使用Spring自定义注解生产Http接口描述信息
- Java注解(自定义方法注解使用及测试)
- java自定义注解及注解使用
- 基于 自定义注解 和 aop 实现使用memcache 对数据库的缓存 示例
- AS3自定义注解的声明与使用
- 自定义底部工具栏及顶部工具栏和Fragment配合使用demo
- Eclipse使用技巧 - 自定义JavaDoc注解和代码模版,提升开发效率和规范性 推荐
- 使用自定义注解来管理所有外部接口
- 使用动态代理+自定义注解控制数据库事务
- Java中的Annotation详解和使用 自定义注解
- spring学习笔记7--使用spring进行面向切面的(AOP)编程(1)注解方式实现
- 使用自定义AnnotationTransactionAttributeSource与TX:注解驱动
- Annotation注解的介绍和使用 自定义注解