您的位置:首页 > 运维架构

自定义注解和aop结合使用---自定义日志记录的实现

2016-03-14 17:33 856 查看
关于aop和自定义注解的知识点本文不做过多阐述,相关资料可去网上查看

这篇文章就讲解的很详细http://www.cnblogs.com/shipengzhi/articles/2716004.html

这里主要写的是个人在学习aop和自定义注解时做的一个小demo,主要实现自定义日志记录的功能。


1、在Maven中加入以下以依赖:

<properties>
<junit.version>4.12</junit.version>
<spring.version>4.1.3.RELEASE</spring.version>
</properties>
<dependencies>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
</dependencies>

<build>
<plugins>
<!-- java编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>



2、在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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 
<context:component-scan base-package="com.annotation" ></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 如果配置此项,所有注入的注解就可以使用了 -->
<context:annotation-config></context:annotation-config>
</beans>



3、编写自定义注解:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @ interface MyLog {
int value() default 11;
}


@Target 用于描述注解的使用范围(即:被描述的注解可以用在什么地方),其取值有:

点击这里点击这里
取值描述
CONSTRUCTOR用于描述构造器(领盒饭)。
FIELD用于描述域(领盒饭)。
LOCAL_VARIABLE用于描述局部变量(领盒饭)。
METHOD用于描述方法。
PACKAGE用于描述包(领盒饭)。
PARAMETER用于描述参数。
TYPE用于描述类或接口(甚至 enum )。
@Retention 用于描述注解的生命周期(即:被描述的注解在什么范围内有效),其取值有:

点击这里点击这里
取值描述
SOURCE在源文件中有效(即源文件保留,领盒饭)。
CLASS在 class 文件中有效(即 class 保留,领盒饭)。
RUNTIME在运行时有效(即运行时保留)。
@Documented 在默认的情况下javadoc命令不会将我们的annotation生成再doc中去的,所以使用该标记就是告诉jdk让它也将annotation生成到doc中去

@Inherited 比如有一个类A,在他上面有一个标记annotation,那么A的子类B不用再次标记annotation就可以继承使用。


4、编写接口和实现类:

public interface UserService {

public void addUser();

public void updateUser();
}


@Service("userService")
public class UserServiceImpl implements UserService {

@MyLog(value=110)//自定义注解
public void addUser() {
System.out.println("---->>>>>add user");
}
public void updateUser() {
System.out.println("----->>>>>update user");
}
}



5、编写切面:

@Aspect
@Component
public class MyAspect {
@Pointcut(value = "execution(* com.annotation.*.*(..))")
private void myPointCut() {
}
@Before("myPointCut() &&  @annotation(log)")
public void myBefore(JoinPoint joinPoint,MyApp log) {
System.out.println("前置通知 : " + joinPoint.getSignature().getName());
}

public void myAfterReturning(JoinPoint joinPoint, Object ret) {
System.out.println("后置通知 : " + ret);
}

public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("前");
// 手动执行目标类
Object obj = joinPoint.proceed();

System.out.println("后");
return obj;
}

public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
System.out.println("抛出异常 : " + e.getMessage());
}

//该表达式指定com/annotation目录下及其所有子目录下的所有带有@MyLog注解的方法体为切点。
@After("myPointCut() &&  @annotation(log)")
public void myAfter(JoinPoint joinPoint,MyLog log) throws NoSuchMethodException,
SecurityException {
//		System.out.println(log.value());
saveLog(log);
//		printLog(joinPoint);
}

private void printLog(JoinPoint joinPoint) throws NoSuchMethodException,
SecurityException {
MyLog log = null;
Class targetClass = joinPoint.getTarget().getClass();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();

Class[] parameterTypes = null;

if (arguments != null) {
int length = arguments.length;
parameterTypes = new Class[length];

for (int i = 0; i < length; ++i) {
parameterTypes[i] = arguments[i].getClass();
}
}

Method method = targetClass.getMethod(methodName, parameterTypes);
if (method != null) {
log = method.getAnnotation(MyLog.class);
}
if (log != null) {
System.out.println("====log======" + log.value());
if(log.value()==110){
System.out.println("日志注解中的值是110");
}
saveLog(log);
}
}

private void saveLog(MyLog log) {
System.out.println("插入日志记录");
System.out.println();
}
}





6、编写测试用例:

@org.junit.Test
public void demo1() {
String xmlPath="/com/annotation/applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
UserService userService = (UserService) applicationContext
.getBean("userService");
userService.addUser();

userService.updateUser();
}


输出结果:
---->>>>>add user

插入日志记录

iam spect2

插入日志记录222

前置通知 : updateUser

----->>>>>update user
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: