springboot 注册 bean

都是 spring 支持的,@Import 我也是从 spring 的文章张直接复制出来的,那边文章详细解释了 bean 的方方面面,感兴趣可以去看

@Configuration、@Bean

相当于 spring 的配置文件,spring 在配置文件中可以配置 bean,用注解方式就是这样的

// 这个类也会作为一个 bean
@Configuration
public class MyConfig {

    // 方法名就是 bean 唯一标识
    @Bean
    public User user(){
        User user = new User();
        user.setUsername("Marry");
        user.setId(12345L);
        return user;
    }

}

要让代码有语义,这种方式可以配置 bean,但是 @Configuration 的语义是代替 spring 的配置文件,如果只是想单纯配置一个 bean 其实这种方式并不清晰

如果只是单纯想配置一个 bean 使用 @Component 方式会更好

@Component

@Component
public class User {
    private Long id;
    private String username;

    // getter setter
}

@Service、@Repository、@Controller 也是注册 bean,但是语义上不同(和上面的 @Configuration 一样,虽然都已配置 bean,但是还是建议符合语义的去配置)

@Import

有三种用法,导入的 bean 的唯一 id 是类的权限定名,spring 的文章有说这个,感兴趣可以自行查询 spring 的方方面面

@ImportResource

导入一个 spring bean 的 xml 文件,把里面用 xml 方式配置的 bean 导入进来

老项目可能还是 srping xml 方式,里面很多 bean,或者很多 bean 的配置文件,总之很多 bean,懒得翻译成注解,直接导入

@EnableConfigurationProperties

用于绑定配置文件和 java 对象,要配合 @ConfigurationProperties 来使用,举个例

  1. 创建一个 java 对象,用于接收配置文件的配置

    @Configuration // 当前配置类也要注册到 spring 容器
    @PropertySource("classpath:myApplication.yml") // 指定自定义配置文件位置和名称,如果不指定就是主配置文件(application.yaml 或 application.properties)
    @ConfigurationProperties(prefix = "person.test") // 配置文件 person.test 的配置绑定到当前类的属性上
    @Data // lombok
    public class MyConfig {
    
        private int id;
    
        private String name;
    }
    
  2. 配置文件

    # 会与绑定 MyConfig.id
    person.test.id=101
    
    # 会与绑定 MyConfig.name
    person.test.name=lisi
    
  3. 启动类使用注解 @EnableConfigurationProperties

    @EnableConfigurationProperties(MyConfig.class)
    @SpringBootApplication
    public class App {
    
        public static void main(String[] args) {
    
            SpringApplication.run(Boot2021Application.class, args);
        }
    
    }
    
  4. 如果想要配置文件中配置属性的时候自动提示,要导入一个依赖

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-configuration-processor</artifactId>
    </dependency>
    
    <!-- 打成的 jar 中再排除,因为只是开发更直观,其实并没有也不影响 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-configuration-processor</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
    

@Conditional 条件装配

  1. 派生了很多注解,很容易顾名思义

  2. 举个 spring 批处理的条件配置

    @Configuration(proxyBeanMethods = false) // true(默认):会使用 cglip 生成代理类,false:不生成代理类。作用是当 @Configuration 有很多 @Bean 的时候优化性能
    @ConditionalOnClass({ JobLauncher.class, DataSource.class }) // 当项目中中存在 JobLauncher、DataSource 类时才配置下面所有 @Bean 方式的 bean
    @AutoConfigureAfter(HibernateJpaAutoConfiguration.class) // 当 HibernateJpaAutoConfiguration 类型的 bean 配置完后,配置当前 bean
    @ConditionalOnBean(JobLauncher.class) // 当存在 JobLauncher 这种类型的 bean 时才配置当前 bean
    @EnableConfigurationProperties(BatchProperties.class) // 自定义配置类,上面刚说了
    @Import(BatchConfigurerConfiguration.class) // 注册一个 BatchConfigurerConfiguration 类型的 bean
    public class BatchAutoConfiguration {
    
    	@Bean
    	@ConditionalOnMissingBean // JobLauncherApplicationRunner 类型的 bean 不存在时才注册
    	@ConditionalOnProperty(prefix = "spring.batch.job", name = "enabled", havingValue = "true", matchIfMissing = true)
    	public JobLauncherApplicationRunner jobLauncherApplicationRunner(JobLauncher jobLauncher, JobExplorer jobExplorer,
    			JobRepository jobRepository, BatchProperties properties) {
    		...
    	}
    
    	@Bean
    	@ConditionalOnMissingBean(ExitCodeGenerator.class) // ExitCodeGenerator 类型的 bean 不存在才注册 JobExecutionExitCodeGenerator
    	public JobExecutionExitCodeGenerator jobExecutionExitCodeGenerator() {
    		return new JobExecutionExitCodeGenerator();
    	}
    
        ...
    
    }
    
  3. 自定义条件

    实现 Condition 接口,复写 matches 方法,当条件返回真才注册 bean

    // 这个就不用加入容器了
    public class EvenWeekDayCondition implements Condition {
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            // 1234567,星期天是 7 不是 0
            int dayOfWeek = LocalDate.now().getDayOfWeek().getValue();
            return dayOfWeek % 2 == 0;
        }
    }
    

    使用条件配置 bean

    @Component
    public class MyBean3 {
    
        /**
         * 如果是周二、周四、周六 就注册 User
         */
        @Conditional(EvenWeekDayCondition.class)
        @Bean
        public User user(){
            return new User();
        }
    }
    
posted @ 2024-07-05 13:39  CyrusHuang  阅读(2)  评论(0编辑  收藏  举报