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();
    }
}
  1. 创建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);
    }
}

  1. 创建测试类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子类中指定的类。

  1. 创建一个类MacOS
public class MacOS {
}
  1. 创建MyImportSelector类实现ImportSelector接口

public class MyImportSelector implements ImportSelector {

    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		// 指定要加载的类
        return new String[]{"my.spring.test4.MacOS"};
    }
}
  1. 更改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();
    }
}
  1. 运行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子类中指定的类。

  1. 定义Ubuntu类
public class Ubuntu {
}
  1. 编写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);
    }
}
  1. 更改配置类
    在@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();
    }
}

  1. 运行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

  1. 写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;
    }
}
  1. 编写配置类MainConfig5

@Configuration
public class MainConfig5 {

    @Bean
    public MyFactoryBean myFactoryBean() {
        return new MyFactoryBean();
    }
}

  1. 运行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

更多看这里吧😁