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);
為什么我在第一節(jié)提到了@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
)姻采。