Spring AOP的注解实现
适用场景:
记录接口方法的执行情况,记录相关状态到日志中。
注解类:LogTag.java
package com.lichmama.spring.annotation; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogTag {
String value() default "";
}
@Target (使用)注解的目标类型:
CONSTRUCTOR 构造方法声明
FIELD 字段声明(包括枚举常量)
LOCAL_VARIABLE 局部变量声明
METHOD 方法声明
PACKAGE 包声明
PARAMETER 参数声明
TYPE 类、接口(包括注释类型)或枚举声明
@Retention 注解的生命周期(默认CLASS):
CLASS 编译器将把注释记录在类文件中,但在运行时VM 不需要保留注释。
RUNTIME 编译器将把注释记录在类文件中,在运行时VM 将保留注释,因此可以反射性地读取。
SOURCE 编译器要丢弃的注释。
@Documented 标记生成javadoc
切面类:ServiceAspect.java
package com.lichmama.spring.aop; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component; import com.lichmama.spring.annotation.LogTag; @Aspect
@Component
public class ServiceAspect { private Log log = LogFactory.getLog(getClass()); @Pointcut("@annotation(com.lichmama.spring.annotation.LogTag)")
private void pointcut() {
} @Before("pointcut()")
public void doBefore(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getMethod().getName();
String logTag = ((LogTag) signature.getMethod().getAnnotation(LogTag.class)).value();
log.info("before calling " + methodName + ", value: " + logTag);
}
}
@Pointcut("@annotation(com.lichmama.spring.annotation.LogTag)") 标注一个切入点,执行任意带有LogTag注解的方法触发。
业务实现:UserServiceImpl.java
package com.lichmama.spring.service.impl; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.lichmama.spring.annotation.LogTag;
import com.lichmama.spring.dao.IUserDAO;
import com.lichmama.spring.entity.User;
import com.lichmama.spring.service.IUserService; @Service
public class UserServiceImpl implements IUserService { @Autowired
private IUserDAO userDAO; @LogTag
@Override
public User getUserById(int id) {
return userDAO.getUserById(id);
} @LogTag
@Override
public void saveUser(User user) {
userDAO.saveUser(user);
} @LogTag
@Override
public void updateUser(User user) {
userDAO.updateUser(user);
} @LogTag("dangerous operation")
@Override
public void deleteUser(int id) {
userDAO.deleteUser(id);
}
}
spring配置文件: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
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> <context:component-scan base-package="com.lichmama.spring.aop" />
<context:component-scan base-package="com.lichmama.spring.dao" />
<context:component-scan base-package="com.lichmama.spring.service" /> <aop:aspectj-autoproxy proxy-target-class="true" />
</beans>
写个测试:
public class TestCase {
private Log log = LogFactory.getLog(getClass());
private ApplicationContext ctx;
@Before
public void initSpringContext() {
ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public void testAOP() {
IUserService userService = ctx.getBean(IUserService.class);
userService.saveUser(new User(1, "lichmama"));
userService.saveUser(new User(2, "james"));
userService.saveUser(new User(3, "dwyane"));
userService.updateUser(new User(2, "bill"));
User user = userService.getUserById(2);
log.info(user.toString());
userService.deleteUser(1);
}
}
16:06:22,517 INFO ServiceAspect:29 - before calling saveUser, value:
16:06:22,549 INFO ServiceAspect:29 - before calling saveUser, value:
16:06:22,549 INFO ServiceAspect:29 - before calling saveUser, value:
16:06:22,550 INFO ServiceAspect:29 - before calling updateUser, value:
16:06:22,551 INFO ServiceAspect:29 - before calling getUserById, value:
16:06:22,551 INFO TestSpring:35 - id: 2, name: bill
16:06:22,551 INFO ServiceAspect:29 - before calling deleteUser, value: dangerous operation
Spring AOP的注解实现的更多相关文章
- spring aop 使用注解方式总结
spring aop的注解方式:和xml的配置方式略有区别,详细如下: 1.首先还是建立需要的切面类:切面类里面定义好切点配置,以及所有的需要实现的通知方法. /** * */ package com ...
- 利用Spring AOP自定义注解解决日志和签名校验
转载:http://www.cnblogs.com/shipengzhi/articles/2716004.html 一.需解决的问题 部分API有签名参数(signature),Passport首先 ...
- spring AOP自定义注解方式实现日志管理
今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在appli ...
- spring AOP自定义注解 实现日志管理
今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在appli ...
- (转)利用Spring AOP自定义注解解决日志和签名校验
一.需解决的问题 部分API有签名参数(signature),Passport首先对签名进行校验,校验通过才会执行实现方法. 第一种实现方式(Origin):在需要签名校验的接口里写校验的代码,例如: ...
- 利用spring AOP 和注解实现方法中查cache-我们到底能走多远系列(46)
主题:这份代码是开发中常见的代码,查询数据库某个主表的数据,为了提高性能,做一次缓存,每次调用时先拿缓存数据,有则直接返回,没有才向数据库查数据,降低数据库压力. public Merchant lo ...
- Spring AOP的注解方式实现
spring也支持注解方式实现AOP,相对于配置文件方式,注解配置更加的轻量级,配置.修改更加方便. 1.开启AOP的注解配置方式 <!-- 开启aop属性注解 --> <aop:a ...
- Spring学习(十八)----- Spring AOP+AspectJ注解实例
我们将向你展示如何将AspectJ注解集成到Spring AOP框架.在这个Spring AOP+ AspectJ 示例中,让您轻松实现拦截方法. 常见AspectJ的注解: @Before – 方法 ...
- spring AOP的注解实例
上一篇写了spring AOP 的两种代理,这里开始AOP的实现了,个人喜欢用注解方式,原因是相对于XML方式注解方式更灵活,更强大,更可扩展.所以XML方式的AOP实现就被我抛弃了. 实现Sprin ...
随机推荐
- C++构造函数虚函数例题
虚函数: #include <iostream> class A { public: A ():m_iVal() { test(); } virtual void func() { std ...
- 《安卓网络编程》之第四篇 处理URL地址
在Android手机系统中,可以通过URL地址获取网络资源.在URL类的众多方法中,可以使用openStream()方法来读取该URL资源的输入流InputStream.在此方法的基础上可以引申出很多 ...
- ES学习笔记
ES学习 1. 安装 1.1 ES 安装配置 curl -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5. ...
- v$session & v$session_wait
(1)v$session v$session视图记录了当前连接到数据库的session信息 Column Description SADDR session address SID Session i ...
- [python] 1、python鼠标点击、移动事件应用——写一个自动下载百度音乐的程序
1.问题描述: 最近百度总爱做一些破坏用户信任度的事——文库金币变券.网盘限速,吓得我赶紧想办法把存在百度云音乐中的歌曲下载到本地. http://yinyueyun.baidu.com/ 可问题是云 ...
- MySql俩种分页区别(注意)
注意俩个分页的区别哦~ SELECT * FROM city LIMIT 2 OFFSET 1; 从第二条记录开始 取二条记录 如下: SELECT * FROM city LIMIT 3,2; 从第 ...
- 整理一些提高C#编程性能的技巧
1.使用StringBuilder代替使用string 连接符 "+" 说明:String类对象是不可变的(只读),一旦创建该对象,就不能修改该对象的值. 对象String对象的重 ...
- Go - concurrency
并发 vs 并行 首先,我们先来搞清楚概念以及并发和并行的区别. 并发 - 利用时间片切换来实现“同时”运行的. 并行 - 利用CPU的多核来实现通过多线程来实现同时运行. Go 语言的设计理念就是通 ...
- MongoDB-配置翻译
Configuration File(配置文件) File Format(文件格式) Use the Configuration File(使用配置文件) Core Options(核心设置) sys ...
- memcache常用命令
一.memcached的基本命令(安装.卸载.启动.配置相关): -p 监听的端口 -l 连接的IP地址, 默认是本机 -d start 启动memcached服务 -d restart 重起m ...