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
)。