Spring学习笔记 加载Bean(其他方式)
除了这些常见的加载Bean方式,还有这些方式
@Conditional注解
这个注解可以按条件加载某些类
1.创建Windows类,和Linux两个类
public class Windows {
}
public class Linux {
}
2.创建配置类MyConfig4
@Configuration
public class MainConfig4 {
// 只有在满足WindowsCondition的条件下加载Windows这个类
@Conditional(value = {WindowsCondition.class})
@Bean
public Windows windows() {
return new Windows();
}
// 只有在满足LinuxCondition的条件下加载Linux这个类
@Conditional(value = {LinuxCondition.class})
@Bean
public Linux linux() {
return new Linux();
}
}
- 创建WindowsCondition和LinuxCondition两个类
matches方法返回true表示满足条件可以加载这个注解标注的类
public class WindowsCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
String sysName = env.getProperty("os.name");
return "Windows 10".equalsIgnoreCase(sysName);
}
}
public class LinuxCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
String sysName = env.getProperty("os.name");
return "linux".equalsIgnoreCase(sysName);
}
}
- 创建测试类MainTest4
public class MainTest4 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig4.class);
for (String name : context.getBeanDefinitionNames()) System.out.println(name);
}
}
在windos下运行输出:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig4
windows
发现确实只输出"windos"而没有输出"Linux"
@Import注解
这个注解可以直接导入某些类
在MainConfig4类中加入@Import注解导入Linux类,因为在windows环境下本身没这个类,因为使用@Import强行导入了所以现在有了,观察输出。
@Configuration
@Import(value = {Linux.class})
public class MainConfig4 {
@Conditional(value = {WindowsCondition.class})
@Bean
public Windows windows() {
return new Windows();
}
@Conditional(value = {LinuxCondition.class})
@Bean
public Linux linux() {
return new Linux();
}
}
输出:
确实出现了"my.spring.test4.Linux",说明Linux这个Bean被成功导入
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig4
my.spring.test4.Linux
windows
ImportSelector接口
通常这个类的子类作为@Import注解的参数,自定义加载ImportSelector子类中指定的类。
- 创建一个类MacOS
public class MacOS {
}
- 创建MyImportSelector类实现ImportSelector接口
public class MyImportSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 指定要加载的类
return new String[]{"my.spring.test4.MacOS"};
}
}
- 更改MainConfig4配置类,@Import参数中添加MyImportSelector.class
@Configuration
@Import(value = {Linux.class, MyImportSelector.class})
public class MainConfig4 {
@Conditional(value = {WindowsCondition.class})
@Bean
public Windows windows() {
return new Windows();
}
@Conditional(value = {LinuxCondition.class})
@Bean
public Linux linux() {
return new Linux();
}
}
- 运行MainTest4查看输出:
多了一个”my.spring.test4.MacOS“类表示导入成功
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig4
my.spring.test4.Linux
my.spring.test4.MacOS
windows
ImportBeanDefinitionRegistrar接口
通常这个类的子类作为@Import注解的参数,自定义加载ImportBeanDefinitionRegistrar子类中指定的类。
- 定义Ubuntu类
public class Ubuntu {
}
- 编写ImportBeanDefinitionRegistrar的子类MyImportBeanDefinitionRegister
public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean used = registry.isBeanNameInUse("Ubuntu");
if (used) return;
RootBeanDefinition definition = new RootBeanDefinition(Ubuntu.class);
// definition 里可以设置scope。definition还有多个兄弟类可以看看功能
definition.setScope(BeanDefinition.SCOPE_SINGLETON);
registry.registerBeanDefinition("Ubuntu", definition);
}
}
- 更改配置类
在@Import中加入"MyImportBeanDefinitionRegister.class"参数
@Configuration
@Import(value = {Linux.class, MyImportSelector.class, MyImportBeanDefinitionRegister.class})
public class MainConfig4 {
@Conditional(value = {WindowsCondition.class})
@Bean
public Windows windows() {
return new Windows();
}
@Conditional(value = {LinuxCondition.class})
@Bean
public Linux linux() {
return new Linux();
}
}
- 运行MainTest4查看输出:
发现输出了Ubuntu类,表示该类被加载
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig4
my.spring.test4.Linux
my.spring.test4.MacOS
windows
Ubuntu
FactoryBean接口
实现FactoryBean接口的子类可以加载bean
- 写FactoryBean的子类MyFactoryBean并实现getObject方法
public class MyFactoryBean implements FactoryBean {
public Object getObject() throws Exception {
return new Soil();
}
public Class<?> getObjectType() {
return Soil.class;
}
public boolean isSingleton() {
return true;
}
}
- 编写配置类MainConfig5
@Configuration
public class MainConfig5 {
@Bean
public MyFactoryBean myFactoryBean() {
return new MyFactoryBean();
}
}
- 运行MainTest5查看输出:
public class MainTest5 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig5.class);
for (String name : context.getBeanDefinitionNames()) System.out.println(name);
Class<?> clazz = context.getBean("myFactoryBean").getClass();
System.out.println("myFactoryBean的类型是: " + clazz);
}
}
输出:
发现bean的id为"myFactoryBean"这个Bean的类型是我们设置的Soil类
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig5
myFactoryBean
myFactoryBean的类型是: class my.spring.test5.Soil