每个开发者在开发一套系统时,必定会开发些服务所需的相关元件,但如何方便建立这些元件又不占用JVM的堆积(Heap)呢?就需要有一个容器暂存这些元件类别,此时,我们才选用Spring这套框架提供了多种注入方式,快速的从IoC配置池中进行注入开发者所需要的Bean元件,让使用者成功地运用相关元件类别进行各类服务运算,在本章节中,我们提供了六种取得Bean类别元件方式,更佳的帮助读者可透过这几种方式可进一步获得所需的解法。
无论使用注解(@Annotation)或XML方式获取所需的Bean元件类别,如同前面章节所述,皆是透过BeanFactory进行获取对应元件,由於本章节主要以注解方式进行注入元件,故以介绍@Autowired进行注入Bean元件原理为主,此方法主要透过AutowiredAnnotationBeanPostProcessor该类别进行实现,Spring主要采用CGLIB中的MethodInterceptor方法取得专案下的所有类别及注解,并将所有相关模式元件储存於IoC配置池元件,我们称此容器元件工厂为BeanFactory,当开发者配置@Autowired时,会自动注入相对应介面之元件或优先权(@Primary)最高之元件,若有多个继承相同介面的元件及未有配置优先权(@Primary)之元件时,而开发者须配置预选元件名称(@Qualifier),或透过ApplicationContext进行获取Bean元件时给予对应预选元件名称,由此可证,开发者所指定注入的物件,必须不可为共通性物件(Object),须为指定物件类别,透过此运作原理即可获取您所配置的元件,相关范例如下。
相关Bean元件获取方法
自动注入最高优先元件
@Primary
@Component("North")
public class NorthCityComponent implements AreaCityComponent {
@Override
public List<CityModel> getCityList() {
.....
.....
.....
}
}
@Autowired
AreaCityComponent primaryComponent;
透过@Qualifer配置预选元件名称进行注入元件
@Component("Center")
public class CenterCityComponent implements AreaCityComponent {
@Override
public List<CityModel> getCityList() {
.....
.....
.....
}
}
@Qualifier("Center")
@Autowired
AreaCityComponent qualifierWithCenterAreaComponent;
透过@Qualifer配置预选元件名称进行注入Override後的Bean元件
@Bean("SouthBean")
public SouthCityComponent getSouthCityComponent() {
return new SouthCityComponent() {
@Override
public List<CityModel> getCityList() {
List<CityModel> cityModels = southCityComponent.getCityList();
cityModels = cityModels.stream().map(cityModel -> {
if (cityModel.getName().equalsIgnoreCase("Penghu County")) {
cityModel.setSpecialLocalProduct("Brown Sugar Steamed Cake");
}
return cityModel;
}).collect(Collectors.toList());
return cityModels;
}
};
}
@Qualifier("SouthBean")
@Autowired
AreaCityComponent overrideWithSouthBeanComponent;
透过ApplicationContext取得Bean元件
AreaCityComponent eastCityComponent;
@Autowired
private ApplicationContext applicationContext;
@Before
public void init() {
eastCityComponent = applicationContext.getBean("East",AreaCityComponent.class);
........
}
透过BeanFactory取得Bean元件
AreaCityComponent fujianCityComponent;
@Autowired
BeanFactory beanFactory;
@Before
public void init() {
........
fujianCityComponent = beanFactory.getBean("Fujian",AreaCityComponent.class);
}
由上述范例我们可以看出,以@Autowired方式经由多层代理进行注入最方便,但透过BeanFactory直接进行注入取得是最快速的方式,供各位开发者作参考及引用。
由此架构图我们可得知开发者所运用的注入式注解(@Autowired)皆透过SpringBeanAutowiringSupport此类别进行代理产生,其架构流程如图一所示,所有注入式注解(@Autowired)标签皆透过AutowiredAnnotationBeanPostProcessor核心类别元件进行产生出InjectionMetadata物件,并触发inject方法产生出对应开发者所需之元件类别,在这过程中必须经过三道逻辑演算法,第一道流程processInjection,区分为方法类型注解(Method Annotation)及栏位类型注解(Field Annotation),此流程会判断所待处理支援间类别是否有配置候选元件名称注解(@Qualifier),有混合型注解配置,会触发postProcessMergedBeanDefinition方法,若其注解作用在方法上,最终会触发postProcessProperties方法,若仅为单一注解(@Autowired),则进行触发processInjection方法,所有元资料(Metadata)配置完後即传送至第二道流程findAutowiringMetadata,若有则选此名称作为Bean Name,若无则以类别名称当做Bean Name,并取得相关快取资料後进行相关逻辑处理,最後进入第三方法buildAutowiringMetadata,此方法会分为栏位型及方法型反射性处理,最後透过ShortcutDependencyDesriptor此类别进行代理产生InjectionMetadata物件处理相关反射元件行为。
图一、@Autowird 注入架构图
Run test task
gradle test
Run open result html
open ./build/reports/tests/test/index.html
测试结果,透过ApplicationContext及@Autowired皆达到预期目标
How to Get Application Context in Spring Boot
String Boot 使用BeanFactory动态取得bean BeanFactory get bean dynamically
Spring Source Analysis: @Autowire Annotation Principle Analysis
Constructor Dependency Injection in Spring
The Spring @Qualifier Annotation
<<: [铁人赛 Day08] 如何使用 memoization 方法减少 useContext 非必要 re-render 的效能问题?
>>: Day8 Function and Interface
外部稽核要求文件需要有保护的机制 , 所以我们引进了 ~ 加密了哪些软件产生的文件 ? Micros...
这是第一次在公开的地方撰写 JavaScript 相关的技术文章,若有错误或需要补充的地方,也欢迎在...
在昨天我们把资料写入了firebase,接下来我们再利用googleHomeTrigger 藉由on...
安全性与演算法 在电脑科学的领域里,每一刻都有数以万计的资料在进行传输,在传输的过程中,是真的安全吗...
<!DOCTYPE html> <html lang="en"...