背景
项目里有一个动态切换数据源的功能,我们是用切面来实现的,是基于注解来实现的,但是父类的方法是可以切换数据源的,如果有一个类直接继承这个类,调用这个子类时,这个子类是不能够切换数据源的,除非这个子类重写父类的方法。
模拟项目例子
注解定义:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation {
String value() default "me";
}
切面定义:
@Order(-1)
@Aspect
@Component
public class MyAspect {
@Before("@within(myAnnotation)")
public void switchDataSource(JoinPoint point, MyAnnotation myAnnotation) {
System.out.println("before, myAnnotation.value : " + myAnnotation.value());
}
}
父类Bean:
@MyAnnotation("father")
public class Father {
public void hello() {
System.out.println("father.hello()");
}
public void hello2() {
System.out.println("father.hello2()");
}
}
子类Bean:
@MyAnnotation("son")
public class Son extends Father {
@Override
public void hello() {
System.out.println("son.hello()");
}
}
配置类:
@Configuration
@EnableAspectJAutoProxy(exposeProxy = true)
public class Config {
@Bean
public Father father() {
return new Father();
}
@Bean
public Son son() {
return new Son();
}
}
测试类:
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class,
MyAspect.class);
Father father = context.getBean("father", Father.class);
father.hello();
father.hello2();
Son son = context.getBean(Son.class);
son.hello();
son.hello2();
}
}
我们定义了一个@Before
通知,方法参数有point, myAnnotation
,方法里输出了myAnnotation.value
的值
下面是输出结果:
before, myAnnotation.value : father
father.hello()
before, myAnnotation.value : father
father.hello2()
before, myAnnotation.value : son
son.hello()
before, myAnnotation.value : father
father.hello2()
从上面的输出结果看出:Son
类重写了hello
方法,myAnnotation.value
的输出的值是son
,hello2
方法没有重写,myAnnotation.value
的输出的值是father
根据需求,我们肯定希望调用Son
类的所有方法时,都希望myAnnotation.value
的输出的值是son
,因此就需要重写父类的所有public
方法
那有没有办法不重写这些方法也能达到相同的效果呢,答案是可以的。
看看使用@within
和@target
的区别
我们分别在父类和子类上加上注解和去掉注解,一起来看看对应的结果
@within
父类无注解,子类有注解:
father.hello()
father.hello2()
before, myAnnotation.value : son
son.hello()
father.hello2()
父类有注解,子类无注解:
before, myAnnotation.value : father
father.hello()
before, myAnnotation.value : father
father.hello2()
before, myAnnotation.value : father
son.hello()
before, myAnnotation.value : father
father.hello2()
父类有注解,