spring使用AOP切换数据源的问题?
定义了一个自定义注解,可以作用在方法和类型,
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD}) // 可以作用在类上、方法上
public @interface DS {
String value() default "";
}
但是有一个问题,单独给类加上面的注解并没有触发AOP,而在方法上使用上面的注解可以触发AOP。这个是什么原因??
@Aspect
@Component
public class DynamicDataSourceAspect {
@Before("@annotation(DS)")
public void beforeSwitchDS(JoinPoint point){
Class<?> target1 = point.getTarget().getClass();
MethodSignature signature = (MethodSignature) point.getSignature();
// 默认使用目标类型的注解,如果没有则使用其实现接口的注解
for (Class<?> clazz : target1.getInterfaces()) {
resolveDataSource(clazz, signature.getMethod());
}
resolveDataSource(target1, signature.getMethod());
}
@After("@annotation(DS)")
public void afterSwitchDS(JoinPoint point){
DataSourceContextHolder.clearDB();
}
/**
* 提取目标对象方法注解和类型注解中的数据源标识 * * @param clazz
* @param method
*/
private void resolveDataSource(Class<?> clazz, Method method) {
try {
Class<?>[] types = method.getParameterTypes();
// 默认使用类型注解-也就是使用定义类上面的注解
if (clazz.isAnnotationPresent(DS.class)) {
DS source = clazz.getAnnotation(DS.class);
System.out.println("类上的注解"+source.value());
DataSourceContextHolder.setDB(source.value());
}
// 方法注解可以覆盖类型注解-也就是使用方法上的注解去替换类上面的注解
Method m = clazz.getMethod(method.getName(), types);
if (m != null && m.isAnnotationPresent(DS.class)) {
DS source = m.getAnnotation(DS.class);
System.out.println("方法上的注解"+source.value());
DataSourceContextHolder.setDB(source.value());
}
} catch (Exception e) {
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
上次debug看了下这个鬼东西,当你用@annotation去做拦截的时候,查找注解,他直接从方法上面查找的,所以你写直接到类上没啥用
入口代码:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary,这个方法,当你类和方法上写注解,结果是不同的
最关键匹配的地方:
org.aspectj.weaver.patterns.ExactAnnotationTypePattern.matches(annotated,parameterAnnotations)
annotated的实现类此时是ReflectionBasedResolvedMemberImpl,
https://gitee.com/baomidou/dy...
多数据源解决方案。
你的问题,可以用现成的切点。
https://gitee.com/baomidou/dy...
private Pointcut buildPointcut() {