springboot⾃定义注解不⽣效情况分析及解决⽅案
前⾔
SpringBoot中⾃定义注解不⽣效情况分析及解决⽅案。
背景:因项⽬需要,通过⾃定义注解实现了⼀个令牌桶功能。在测试的时候,⾃定义注解加在Controller层的带RequestMapping注解的⽅法上,Service层中实现⾃接⼝的⽅法上,都能⽣效。⼀旦把注解加在普通⽅法上,注解就失效了。⽹上了很多资料,有⼀种说法是包扫描的问题。我遇到的情况不是包扫描不到的问题。⽆意中看到⼀个讲Spring Aop实现机制的⽂章,提到了动态代理,参照⽂章修改项⽬,解决了问题。下⾯详细记录⼀下问题及处理问题的⽅法
⼀、Spring AOP的实现机制
基于spring aop实现的注解,在spring中,如果有aop实现,那么容器注⼊的是该类的代理类。spring aop的动态代理有两种:⼀种是jdk 的动态代理,⼀种是基于CGLIB的,这两个的区别⾃⼰查资料。在这⾥我知道了aop是基于动态代理实现的。看下⾯的代码:
@Service
public class RateLimitServiceImpl implements RateLimitService {
@Autowired
RedisTemplate<String, Serializable> redisTemplate;
@Override
public String testRateLimit() {
return test();
}
@RateLimit(key = "test", time = 10, count = 5)
public String test(){
RedisAtomicInteger entityIdCounter = new RedisAtomicInteger("entityIdCounter", ConnectionFactory());
String date = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
return date + "累计访问次数:" + AndIncrement();
}
}
上⼀级⽅法在调⽤testRateLimit⽅法的时候,是通过的spring托管的类的代理请求的。如果@RateLimit注解放在testRateLimit⽅法上,那么注解是可以⽣效的。但是注解如果如⽰例代码中那样放在普通的类⽅法test上,那么注解是不会⽣效的。这是因为,test⽅法的调⽤是在testRateLimit⽅法内部调⽤的,所以在这⾥实际调⽤test的是真实对象,不是代理对象。所以test⽅法上的限流注解没有⽣效。也就是说内部调⽤不⾛代理类,所以附加的注解也就不会执⾏了。那么我们的解决思路就出来了,怎么样让test被代理类调⽤。
⼆、EnableAspectJAutoProxy的使⽤
@EnableAspectJAutoProxy - 开启对AspectJ⾃动代理技术
1.使⽤XML的配置:
<aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true" />
2.使⽤注解配置
我是springboot项⽬,使⽤的注解来配置
@Service
@EnableAspectJAutoProxy(exposeProxy = true)
public class RateLimitServiceImpl implements RateLimitService {
@Autowired
RedisTemplate<String, Serializable> redisTemplate;
@Override
public String testRateLimit() {
return ((RateLimitServiceImpl)AopContext.currentProxy()).test();
}
@RateLimit(key = "test", time = 10, count = 5)
public String test(){
RedisAtomicInteger entityIdCounter = new RedisAtomicInteger("entityIdCounter", ConnectionFactory());
String date = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
return date + "累计访问次数:" + AndIncrement();
}
}
这段代码跟上⼀段代码的区别就是RateLimitServiceImpl类上多了⼀个EnableAspectJAutoProxy注解,testRateLimit⽅法的实现,调⽤test⽅法的⽅式变成了通过AopContext.CurrentProxy来代理
这样,问题就解决了。
总结springboot aop
以上就是对于特殊业务场景注解的使⽤⽅法说明,并不仅限于⾃定义注解,官⽅注解也同样适⽤。感
谢两篇⽂章的⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论