Background
@Inherited是一种元注解(指的是修饰注解的注解)。注意:
@Inherited修饰的注解(例如@My)只有修饰在类上,才会起到所谓的继承作用,修饰字段、方法是不能起到继承作用。
Java注解学习-@Inherited
关于@Autowired
举例说明。现在有父类FatherService,其有个字段TargetService被@Autowired修饰;
@Service
public class FatherService {
@Autowired
public TargetService targetService;
}
子类SonService继承父类:
@Service
public class SonService extends FatherService{
}
测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
@Slf4j
public class SonServiceTest {
@Autowired
SonService sonService;
@Test
public void test() throws Exception {
Assert.assertNotEquals(null, sonService.targetService);
}
}
请问:测试类中的sonService.targetService是否为null?
答案是不为null。原因是Spring的AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement.inject会对一个类的本身的字段和其所有父类的字段进行遍历,凡是含有@Autowired的字段都会被注入。我用反射方式来近乎实现这个结果:
SonService sonService = new SonService();
// 被注入的bean
TargetService ts = new TargetService();
// 获取对象的子类的父类的该字段
Field fatherField = sonService.getClass().getSuperclass().getDeclaredField("targetService");
// 注入
fatherField.set(sonService, ts);
为什么我在第一节提到了@Inherited?我原以为@Autowired是因为被@Inherited修饰过,所以子类才能继承父类的被注入字段。实际上@Inherited是这么用的:
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface My {
}
@My // 用到类上才可以被子类SonService继承
@Service
public class FatherService {
@Autowired
public TargetService targetService;
}
Extension
如果我把上面的子类改为:
@Service
public class SonService extends FatherService{
public TargetService targetService;
}
实际上这时,sonService有了两个字段:targetService和父类的targetService。只不过父类的targetService属于隐形字段(在调用sonService.targetService调用的是targetService)。