spring中⾃定义注解(annotation)与AOP中获取注解___使⽤aspectj。。。spring中⾃定义注解(annotation)与AOP中获取注解
⼀、⾃定义注解(annotation)
⾃定义注解的作⽤:在反射中获取注解,以取得注解修饰的类、⽅法或属性的相关解释。
package;
import Documented;
import ElementType;
import Retention;
import RetentionPolicy;
import Target;
//⾃定义注解相关设置
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public@interface LogAnnotation {
//⾃定义注解的属性,default是设置默认值
String desc()default"⽆描述信息";
}
⼆、⾃定义注解的使⽤
package;
import LogAnnotation;
import JdbcUtil;
import Autowired;
import Service;
@Service
public class UserService {
//与其它注解⼀样的使⽤
@LogAnnotation(desc="this is UserService")
public void add(){
System.out.println("");
}
resource和autowired注解的区别}
三、AOP中获取注解
// 环绕通知:类似与动态代理的全过程
/
/ 携带参数ProceedingJoinPoint,且必须有返回值,即⽬标⽅法的返回
@Around(value ="execution(* me.lichunlong.spring.service.*.*(..)) && @annotation(log)")
public Object aroundMethod(ProceedingJoinPoint pjd, LogAnnotation log){
Object result =null;
System.out.println(log.desc());
try{
System.out.println("前置通知");
result = pjd.proceed();
System.out.println("后置通知");
}catch(Throwable e){
System.out.println("异常通知");
}
System.out.println("返回通知");
return result;
}
使⽤aspectj的@Around注解实现⽤户操作和操作结果⽇志
⾃定义注解,将需要记录⽇志的⽅法进⾏标记
/*
* 常⽤注解说明:
* 1. RetentionPolicy(保留策略)是⼀个enum类型,有三个值
* SOURCE -- 这个Annotation类型的信息只会保留在程序源码⾥,源码如果经过了编译后,Annotation的数据就会消失,并不会保留在编译好的.class⽂件⾥
* CLASS -- 这个Annotation类型的信息保留在程序源码中,同时也会保留在编译好的.class⽂件⾥⾯,在执⾏的时候,并不会把这⼀些信息加载到虚拟机(J VM)中去.注意⼀下,当你没有设定⼀个Annotation类型的Retention值时,系统默认值是CLASS。
* RUNTIME -- 在源码、编译好的.class⽂件中保留信息,在执⾏的时候会把这⼀些信息加载到JVM中去的。
*
* 2.ElementType @Target中的ElementType⽤来指定Annotation类型可以⽤在哪些元素上
* TYPE(类型) -- 在Class,Interface,Enum和Annotation类型上
* FIELD -- 属性上
* METHOD -- ⽅法上
* PARAMETER -- 参数上
* CONSTRUCTOR -- 构造函数上
* LOCAL_VARIABLE -- 局部变量
* ANNOTATION_TYPE -- Annotation类型上
* PACKAGE -- 包上
*
* 3.Documented -- 让这个Annotation类型的信息能够显⽰在API说明⽂档上;没有添加的话,使⽤javadoc⽣成的API⽂件不到这个类型⽣成的信息
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public@interface TestAnnotation {
//操作内容
String operation()default"";
}
配置Aspect,创建规则和⽅法
package;
import TestAnnotation;
import LogMessage;
import ReturnMessage;
import ProceedingJoinPoint;
import Around;
import Aspect;
import Component;
import Date;
/*
* 特别注意: Spring的配置⽂件中添加:
*
* <aop:aspectj-autoproxy />
* l中天机
* <!--通知spring使⽤cglib⽽不是jdk的来⽣成代理⽅法 AOP可以拦截到Controller-->
* <aop:aspectj-autoproxy proxy-target-class="true"/>
*
* <aop:config>节点中proxy-target-class="true"不为true时。
* 当登录的时候会报这个异常java.lang.NoSuchMethodException: $Proxy54.login(),
*/
@Aspect
@Component
public class LogInterceptor {
/**
* 环绕通知⽤于拦截指定内容,记录⽤户的操作
* pj:ProceedingJoinPoint 是切⼊点对象
* annotation:TestAnnotation ⾃定义的注解对象
* object:Object ⽅法的第⼀个参数
*/
@Around(value ="@annotation(annotation) && args(object,..) ", argNames ="pj,annotation,object") public Object interceptorTest(ProceedingJoinPoint pj,
TestAnnotation annotation, Object object)throws Throwable {
System.out.println("执⾏⽅法 "+pj.getSignature().getName());
// 初始化⽇志数据
LogMessage logMessage =new LogMessage();
// 获取操作的参数
Object[] args = pj.getArgs();
if(args.length>=1){
// 写⼊id
logMessage.setManId(args[0].toString());
}
// 写⼊操作时间
logMessage.setDate(new Date().getTime());
// 写⼊操作名
logMessage.setOperation(annotation.operation());
// 执⾏操作,获取操作的返回结果
ReturnMessage returnMessage =(ReturnMessage) pj.proceed();
// 写⼊操作结果
logMessage.Status());
// 如果操作结果失败,写⼊失败原因
if(!logMessage.isSuccess()){
logMessage.Msg());
}
/
/输出⽇志信息
System.out.String());
// 输出结束标识
System.out.println("执⾏结束 "+pj.getSignature().getName());
// 返回操作的原本结果
return returnMessage;
}
}
添加到配置⽂件xml
<annotation-config/>
<aspectj-autoproxy />
<component-scan base-package="sumer"/>
⽇志封装
操作结果封装
记录controller的⽇志记录,单纯返回固定的测试数据
@RequestMapping("aopTest")
@ResponseBody
@TestAnnotation(operation ="测试AOP⽇志记录") public ReturnMessage aopTest(
@RequestParam(name ="manId")String manId){
return new ReturnMessage(false,"",null);
}
使⽤PostMan测试接⼝,数据返回⽆误
查看控制台⽇志信息,操作名,参数,结果和时间都被记录
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论