比如要注入Student這個(gè)類
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private Integer id = 100;
private String name = "zhangsan";
private Integer age = 20;
private Boolean sex = true;
}
第一種
- 使用@Bean注解友驮,這種方式是最簡單的方式;
示例:
@Configuration
public class StudentConfig {
@Bean
public Student getStudent() {
return new Student();
}
}
- 測試:
@SpringBootTest
public class TestDemoApplicationTests {
@Autowired
private Student student;
@Test
void getBean() {
System.out.println(student);
}
}
結(jié)果:
第二種
- 通過實(shí)現(xiàn)ImportSelector接口和結(jié)合@Import注解來注入驾锰;
這種方式其實(shí)也是SpringBoot的自動(dòng)注入方式卸留,這里只是簡單實(shí)現(xiàn)。 - StudentImportSelector
public class StudentImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
String[] str = {"com.chitang.domain.Student"};
return str;
}
}
@Configuration
@Import(StudentImportSelector.class)
public class StudentConfiguration {
}
通過@Import注解進(jìn)行導(dǎo)入椭豫。
-
看看SpringBoot是怎么做的耻瑟。
順便對比一下SpringBoot相應(yīng)的實(shí)現(xiàn)方式,不相關(guān)的代碼省略掉了赏酥。
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
這里AutoConfigurationImportSelector類實(shí)現(xiàn)了DeferredImportSelector接口喳整,這個(gè)接口其實(shí)就是ImportSelector的子接口,兩者有點(diǎn)區(qū)別裸扶,這里不做解釋框都。
看一下selectImports方法中最后return的時(shí)候StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()),返回的就是一個(gè)String類型的數(shù)組呵晨,數(shù)組里面就是需要自動(dòng)裝配類的路徑魏保。所以在我自己的selectImports方法中,就直接返回了Student的路徑摸屠。
-
測試
第三種
- 通過實(shí)現(xiàn)ImportBeanDefinitionRegistrar接口和結(jié)合@Import注解來注入谓罗。
public class StudentRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Student.class);
registry.registerBeanDefinition(Student.class.getSimpleName(), beanDefinitionBuilder.getBeanDefinition());
}
}
@Configuration
//@Import(StudentImportSelector.class)
@Import(StudentRegistrar.class)
public class StudentConfiguration {
}
- 使用方式和第二種一樣。
-
測試
- 來看看這種方式在源碼中的實(shí)踐吧季二!
-
點(diǎn)進(jìn)ImportBeanDefinitionRegistrar接口中檩咱,看一下他的實(shí)現(xiàn)類。
- 我們點(diǎn)進(jìn)一個(gè)稍微熟悉的實(shí)現(xiàn)類中去看看吧胯舷,就BeanPostProcessorsRegistrar吧刻蚯。
public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
private ConfigurableListableBeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (beanFactory instanceof ConfigurableListableBeanFactory) {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
}
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
if (this.beanFactory == null) {
return;
}
registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
WebServerFactoryCustomizerBeanPostProcessor.class,
WebServerFactoryCustomizerBeanPostProcessor::new);
registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",
ErrorPageRegistrarBeanPostProcessor.class, ErrorPageRegistrarBeanPostProcessor::new);
}
private <T> void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name,
Class<T> beanClass, Supplier<T> instanceSupplier) {
if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass, instanceSupplier);
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(name, beanDefinition);
}
}
}
都是在registerBeanDefinitions方法中進(jìn)行注入的,只是他這里的方式比較完善桑嘶,我寫的比較簡單芦倒。大家如果愿意的話,可以把這一段直接copy到自己需要用的地方不翩,都不用改的兵扬,哈哈。
-
再來看看口蝠,他怎么讓這個(gè)類生效的呢器钟?往上劃,滑到最上面去妙蔗。
-
最終也是使用@Import注解來干的傲霸。
細(xì)心的小伙伴可能會(huì)發(fā)現(xiàn),有個(gè)熟悉的名字出現(xiàn)了。
是的昙啄,SpringBoot自帶的3個(gè)web容器也是在這里導(dǎo)入的穆役。
-
來拓展一下吧,點(diǎn)進(jìn)EmbeddedTomcat類中梳凛,發(fā)現(xiàn)它也是個(gè)靜態(tài)內(nèi)部類耿币。
-
她是想注入TomcatServletWebServerFactory這個(gè)類,那我們進(jìn)去看看韧拒。
這個(gè)類就不多說了淹接,我看看好玩的,這里的port叛溢,我們一直往上跟塑悼,一直到AbstractConfigurableWebServerFactory類中,最后發(fā)現(xiàn)楷掉,我們平常最熟悉的8080端口居然在這里待著厢蒜。
好了,這就是今天給大家分享的一些知識了烹植,拜拜郭怪。