自定义注解及利用AOP对方法进行加强处理
自定义注解
自定义的关键字为@Interface
原注解
原注解是注解的注解,有一下几种
@Retention: 定义注解的保留策略
@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target
@Target:注解的目标,即注解的范围,可以为类或者方法或者同时在类和方法等
@Documented
说明该注解将被包含在javadoc中
例子如下
/**
*
* @author 734621
*
*/
@Target({ElementType.METHOD})//注解定义在方法还是类中,是一个数组,即可以同时定义在类和方法中
@Retention(RetentionPolicy.RUNTIME)// 注解会在class字节码文件中存在,在运行时可以通过反射获取到
public @interface CommonLogging {
LogType type() default LogType.ALL;
}
利用AOP及注解对方法进行加强
即通过Spring的AOP及注解的范围对方法进行加强,加强的意思是在方法执行前或后加一些东西并且可以改变方法的行为。例子如下
package com.sf.rps.spring.apect;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
/**
* 切面类,定义注解需要做的操作
* @author 734621
*
*/
@Component//加入Spring管理
@Aspect//标注此类是切面类
public class CommonLoggingAdvice implements Ordered{//Ordered是如果有多个注解的话会先执行哪个注解,后执行哪个注解,order的值越小就越先执行,执行完方法后则相反
/**
* 定义切入点,切入范围,即定义了注解CommonLogging才会执行
*/
@Pointcut(value = "@annotation(com.sf.rps.spring.apect.CommonLogging)")
private void pointcut(){
}
/**
* 注解中的pointcut()和logging对应方法的参数值,缺一不可
* @param joinPoint
* @param logging
* @return
*/
@Around(value = "pointcut() && @annotation(logging)")
public Object otherAround(ProceedingJoinPoint joinPoint,CommonLogging logging){
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
Method method = signature.getMethod();//获得被注解的方法
Object [] args = joinPoint.getArgs();//获得被注解的参数
Object result = null;
System.out.println("2222222222");
if (LogType.BEFORE == logging.type()) {//判断注解里的值
before(method.getName());
result = executeMethod(joinPoint);//执行方法
}else if(LogType.AFTER == logging.type()){
result = executeMethod(joinPoint);
after(method.getName());
}else{
before(method.getName());
result = executeMethod(joinPoint);
after(method.getName());
}
return result;
}
/**
* 执行完被注解的方法后需执行的方法
* pointcut() && logging 与方法参数必须保持一致
* @param joinPoint
* @param logging
* @param result被注解方法的返回值
* @return
*/
@AfterReturning(value = "pointcut() && @annotation(logging)",returning = "result")
public Object afterRunning(JoinPoint joinPoint,CommonLogging logging,Object result){
System.out.println("-------afterRunning---------");
return result;
}
public Object executeMethod(ProceedingJoinPoint joinPoint){
try {
return joinPoint.proceed();//执行被注解的方法,并且返回返回值
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void before(String methodName){
System.out.println("方法"+methodName+"将开始执行!");
}
public void after(String methodName){
System.out.println("方法"+methodName+"已经执行完毕!");
}
@Override
public int getOrder() {
// TODO Auto-generated method stub
return 10;
}
}
import org.springframework.stereotype.Component;
@Component("loggerServer")
public class LoggerServer {
@CommonLogging(type = LogType.ALL)
public String getLoggerMessage(){
System.out.println("this is method getLoggerMessage");
return "Simba";
}
}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(value=SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = {"classpath:beanFactory.xml"})
public class TestLogType {
@Resource(name = "loggerServer")
private LoggerServer loggerServer;
@Test
public void testLogType(){
System.out.println(loggerServer.getLoggerMessage());
}
}
定义配置文件beanFactory.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:tx="http://www.springframework.org/schema/tx"
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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 开启注解 -->
<context:annotation-config/>
<!-- 开启切面 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<!-- 定义那个包下可以注解 -->
<context:component-scan base-package="com.sf.rps.spring.apect"></context:component-scan>
</beans>
最后执行结果如下:
2222222222
方法getLoggerMessage将开始执行!//方法执行前的操作
this is method getLoggerMessage
方法getLoggerMessage已经执行完毕!//方法执行后的操作
-------afterRunning---------//方法执行后的操作
Simba//返回值
方法getLoggerMessage将开始执行!//方法执行前的操作
this is method getLoggerMessage
方法getLoggerMessage已经执行完毕!//方法执行后的操作
-------afterRunning---------//方法执行后的操作
Simba//返回值