目标: 创建自定义注解,在方法上使用自定义注解完成该方法被调用后日志的记录
问题: 1:自定义注解和aop如何关联到一起
2:使用aop过程中几点不注意导致切面无法调用
一:配置自定义注解和切面 完成日志记录
1.定义自定义的注解
@Target({ElementType.PARAMETER, ElementType.METHOD}) //定义注解可以使用的范围
@Retention(RetentionPolicy.RUNTIME) //定义注解生效的时间
@Documented
public @interface LogAnno{} //可以在注解体中定义自己想自定义的字段,一般定义 在该切入点的方法执行什么操作等信息 比如: add操作, 菜单
2.切面
spring配置文件(我使用注解事务,没有配置手动事务管理)
<!--开启注解扫描->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 注解方式配置事物 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!--启用cglib代理创建切面-->
<aop:aspectj-autoproxy proxy-target-class="true"/>
切面类
@Aspect
@Component
public class MyLoggerAspect {
@Autowired
private LoggerService loggerService; //注入loggerService是使用loggerService中的方法将日志录入数据库
private static final Logger logger = LoggerFactory.getLogger(MyLoggerAspect. class);
@Pointcut("@annotation(com.wenwuxiaoxue.managementUI.annotation.LogAnno)")
public void controllerAspect(){} //这个地方是自定义注解和切面类结合的点
/*@Before("controllerAspect()")
public void doBefore(JoinPoint joinPoint){
System.out.println("--------before------");
if(logger.isInfoEnabled()){
logger.info("before " + joinPoint);
}
}
//后置通知
@Around("controllerAspect()")
public void doAround(JoinPoint joinPoint){
System.out.println("--------doAround------");
if(logger.isInfoEnabled()){
logger.info("doAround " + joinPoint);
}
}*/
@After("controllerAspect()")
public void doAfter(JoinPoint joinPoint){
System.out.println("--------doAfter------");
if(logger.isInfoEnabled()){
logger.info("doAfter " + joinPoint);
}
loggerService.addSysLog(new SysLog(),new HashMap<String,Object>());
}
}
切面类描述: 使用@Aspect注解将该类定义成一个切面类,@Component使spring可以扫描到(也可以在配置文件里使用<bean>进行定义,或者使用@Configuration注解类进行定义)
@Pointcut定义了切入的方式, 在这个地方我使用了定义一个方法,然后在该方法上使用这个注解,然后在前置/后置/环绕等通知上直接使用这个方法名称就可以了,相当于抽取出来了.当然你可以直接把@Pointcut里面的内容写到通知方法上.
这样就完成了注解和通知的整合,使用的时候只需要在对应的方法上使用自定义注解就可以了
注意点:1 如果前台是ajax请求,你又是通过controller中的方法直接return回去的,而你的自定义注解或者切面类正好在controller的方法上,那么切面是不会生效的.
(不知道把响应ajax的方法写入到拦截器中会不会解决切面失效问题.没有测试,我一直想将普通请求和ajax请求整合到一个拦截器中,通过判断请求头是否是ajax然后按照不同的方式响应,但是目前还没有实现,也许后面会进行改造)
2.另外一个失效的地方就是,当你在切面类同时写了前置,环绕,后置通知以后,切面生效的方法后续代码是不执行的,我不知道问题出在哪里,当我只使用后置通知时,方法就恢复正常,所有的数据都会加载出来. 所以在上面的代码中我将前两个通知注释掉了. 下面贴一下失效的图