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) {
        }
    }
}
阅读 2.5k
2 个回答

上次debug看了下这个鬼东西,当你用@annotation去做拦截的时候,查找注解,他直接从方法上面查找的,所以你写直接到类上没啥用
入口代码:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary,这个方法,当你类和方法上写注解,结果是不同的
image.png

最关键匹配的地方:
org.aspectj.weaver.patterns.ExactAnnotationTypePattern.matches(annotated,parameterAnnotations)
image.png
annotated的实现类此时是ReflectionBasedResolvedMemberImpl,
image.png

https://gitee.com/baomidou/dy...
多数据源解决方案。

你的问题,可以用现成的切点。
https://gitee.com/baomidou/dy...

private Pointcut buildPointcut() {

    Pointcut cpc = new AnnotationMatchingPointcut(DS.class, true);

    Pointcut mpc = new AnnotationMethodPoint(DS.class);

    return new ComposablePointcut(cpc).union(mpc);

}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题