Spring @Conditional通过条件控制bean注册过程

目录
  • Spring对配置类的处理主要分为2个阶段
    • 配置类解析阶段
    • bean注册阶段
  • Spring对配置类处理过程
    • 源码位置
    • 整个过程大致的过程
    • ConfigurationCondition接口
    • Conditional使用的3步骤
  • 阻止配置类的处理
  • bean不存在的时候才注册
  • 根据环境选择配置类
  • Condition指定优先级
  • ConfigurationCondition使用
    • 自定义一个ConfigurationCondition类
  • 总结

Spring对配置类的处理主要分为2个阶段

配置类解析阶段

会得到一批配置类的信息,和一些需要注册的bean

bean注册阶段

将配置类解析阶段得到的配置类和需要注册的bean注册到spring容器中

看一下什么是配置类,类中有下面任意注解之一的就属于配置类:

类上有@Compontent注解,@Configuration注解,@CompontentScan注解,@Import注解,@ImportResource注解以及类中有@Bean标注的方法 的都是配置类

判断一个类是不是一个配置类,是否的是下面这个方法,有兴趣的可以看一下:

org.springframework.context.annotation.ConfigurationClassUtils#isConfigurationCandidate

spring中处理这2个过程会循环进行,直到完成所有配置类的解析及所有bean的注册。

Spring对配置类处理过程

源码位置

org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

整个过程大致的过程

通常我们会通过new AnnotationConfigApplicationContext()传入多个配置类来启动spring容器

spring对传入的多个配置类进行解析

配置类解析阶段:这个过程就是处理配置类上面6中注解的过程,此过程中又会发现很多新的配置类,比如@Import导入的一批新的类刚好也符合配置类,而被@CompontentScan扫描到的一些类刚好也是配置类;此时会对这些新产生的配置类进行同样的过程解析

bean注册阶段:配置类解析后,会得到一批配置类和一批需要注册的bean,此时spring容器会将这批配置类作为bean注册到spring容器,同样也会将这批需要注册的bean注册到spring容器

经过上面第3个阶段之后,spring容器中会注册很多新的bean,这些新的bean中可能又有很多新的配置类

Spring从容器中将所有bean拿出来,遍历一下,会过滤得到一批未处理的新的配置类,继续交给第3步进行处理

step3到step6,这个过程会经历很多次,直到完成所有配置类的解析和bean的注册

从上面过程中可以了解到:

可以在配置类上面加上@Conditional注解,来控制是否需要解析这个配置类,配置类如果不被解析,那么这个配置上面6种注解的解析都会被跳过

可以在被注册的bean上面加上@Conditional注解,来控制这个bean是否需要注册到spring容器中

如果配置类不会被注册到容器,那么这个配置类解析所产生的所有新的配置类及所产生的所有新的bean都不会被注册到容器

一个配置类被spring处理有2个阶段:配置类解析阶段、bean注册阶段(将配置类作为bean被注册到spring容器)。

如果将Condition接口的实现类作为配置类上@Conditional中,那么这个条件会对两个阶段都有效,此时通过Condition是无法精细的控制某个阶段的,如果想控制某个阶段,比如可以让他解析,但是不能让他注册,此时就就需要用到另外一个接口了:ConfigurationCondition

ConfigurationCondition接口

相对于Condition接口多了一个getConfigurationPhase方法,用来指定条件判断的阶段,是在解析配置类的时候过滤还是在创建bean的时候过滤。

Conditional使用的3步骤

自定义一个类,实现Condition或ConfigurationCondition接口,实现matches方法

在目标对象上使用@Conditional注解,并指定value的指为自定义的Condition类型

启动spring容器加载资源,此时@Conditional就会起作用了

阻止配置类的处理

在配置类上面使用@Conditional,这个注解的value指定的Condition当有一个为false的时候,spring就会跳过处理这个配置类。

自定义一个Condition类:

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
 * 自定义控制器
 *
 * @author maruifu
 * @date 2022-12-07
 */
@Configuration
public class DslLogCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 读取配置文件application.yml中 spring.elasticsearch.dslLog: true 配置
        YamlPropertiesFactoryBean y=new YamlPropertiesFactoryBean();
        y.setResources(new ClassPathResource("application.yml"));
        return (Boolean) y.getObject().get("spring.elasticsearch.dslLog");
     }
}

matches方法内部我们可以随意发挥,此处为了演示效果读取的配置文件。

来个配置类,在配置类上面使用上面这个条件,此时会让配置类失效,如下:

import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
/**
 * 用于打印dsl语句
 */
@Configuration
public class EsConfig {
    @Value("${spring.elasticsearch.rest.uris}")
    private String elasticsearchHost;
    @Conditional(DslLogCondition.class)
    @Bean(destroyMethod = "close")
    public RestHighLevelClient restClient() {
        ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo(elasticsearchHost).build();
        RestHighLevelClient client = RestClients.create(clientConfiguration).rest();
         return client;
    }
}

1:使用了自定义的条件类

2:通过@Bean标注这restClient这个方法,如果这个配置类成功解析,会将restClient方法的返回值作为bean注册到spring容器

bean不存在的时候才注册

IService接口有两个实现类Service1和Service1,这两个类会放在2个配置类中通过@Bean的方式来注册到容器,此时我们想加个限制,只允许有一个IService类型的bean被注册到容器。

可以在@Bean标注的2个方法上面加上条件限制,当容器中不存在IService类型的bean时,才将这个方法定义的bean注册到容器,下面来看代码实现。

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.core.type.AnnotatedTypeMetadata;
import java.util.Map;
public class OnMissingBeanCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取bean工厂
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //从容器中获取IService类型bean
        Map<String, IService> serviceMap = beanFactory.getBeansOfType(IService.class);
        //判断serviceMap是否为空
        return serviceMap.isEmpty();
    }

上面matches方法中会看容器中是否存在IService类型的bean,不存在的时候返回true

来一个配置类负责注册Service1到容器

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfig1 {
    @Conditional(OnMissingBeanCondition.class) //@1
    @Bean
    public IService service1() {
        return new Service1();
    }
}

再来一个配置类负责注册Service2到容器

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfig2 {
    @Conditional(OnMissingBeanCondition.class)//@1
    @Bean
    public IService service2() {
        return new Service2();
    }

来一个总的配置类,导入另外2个配置类

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({BeanConfig1.class,BeanConfig2.class})
public class MainConfig {
}

根据环境选择配置类

平常我们做项目的时候,有开发环境、测试环境、线上环境,每个环境中有些信息是不一样的,比如数据库的配置信息,下面我们来模拟不同环境中使用不同的配置类来注册不同的bean

自定义一个条件的注解

import org.springframework.context.annotation.Conditional;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Conditional(EnvCondition.class) //@1
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EnvConditional {
    //环境(测试环境、开发环境、生产环境)
    enum Env { //@2
        TEST, DEV, PROD
    }
    //环境
    Env value() default Env.DEV; //@3
}
  • @1:注意这个注解比较特别,这个注解上面使用到了@Conditional注解,这个地方使用到了一个自定义Conditione类:EnvCondition
  • @2:枚举,表示环境,定义了3个环境
  • @3:这个参数用指定环境 上面这个注解一会我们会用在不同环境的配置类上面

下面来3个配置类 让3个配置类分别在不同环境中生效,会在这些配置类上面使用上面自定义的@EnvConditional注解来做条件限定。

每个配置类中通过@Bean来定义一个名称为name的bean,一会通过输出这个bean来判断哪个配置类生效了。

下面来看3个配置类的代码

测试环境配置类

package com.javacode2018.lesson001.demo25.test2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnvConditional(EnvConditional.Env.TEST)//@1
public class TestBeanConfig {
    @Bean
    public String name() {
        return "我是测试环境!";
    }
}
  • @1指定的测试环境

开发环境配置类

package com.javacode2018.lesson001.demo25.test2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnvConditional(EnvConditional.Env.DEV) //@1
public class DevBeanConfig {
    @Bean
    public String name() {
        return "我是开发环境!";
    }
}
  • @1:指定的开发环境

生产环境配置类

package com.javacode2018.lesson001.demo25.test2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnvConditional(EnvConditional.Env.PROD) //@1
public class ProdBeanConfig {
    @Bean
    public String name() {
        return "我是生产环境!";
    }
}
  • @1:指定的生产环境

下面来看一下条件类:EnvCondition

条件类会解析配置类上面@EnvConditional注解,得到环境信息。

然后和目前的环境对比,决定返回true还是false,如下:

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class EnvCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //当前需要使用的环境
        EnvConditional.Env curEnv = EnvConditional.Env.DEV; //@1
        //获取使用条件的类上的EnvCondition注解中对应的环境
        EnvConditional.Env env = (EnvConditional.Env) metadata.getAllAnnotationAttributes(EnvConditional.class.getName()).get("value").get(0);
        return env.equals(curEnv);
    }
}

@1:这个用来指定当前使用的环境,此处假定当前使用的是开发环境,这个我们以后可以任意发挥,比如将这些放到配置文件中,此处方便演示效果。

Condition指定优先级

多个Condition按顺序执行 @Condtional中value指定多个Condtion的时候,默认情况下会按顺序执行,还是通过代码来看一下效果。

下面代码中定义了3个Condition,每个Condition的matches方法中会输出当前类名,然后在配置类上面同时使用这3个Condition

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.AnnotatedTypeMetadata;
class Condition1 implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        System.out.println(this.getClass().getName());
        return true;
    }
}
class Condition2 implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        System.out.println(this.getClass().getName());
        return true;
    }
}
class Condition3 implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        System.out.println(this.getClass().getName());
        return true;
    }
}
@Configuration
@Conditional({Condition1.class, Condition2.class, Condition3.class})
public class MainConfig5 {
}

指定Condition的顺序 自定义的Condition可以实现PriorityOrdered接口或者继承Ordered接口,或者使用@Order注解,通过这些来指定这些Condition的优先级。

排序规则:先按PriorityOrdered排序,然后按照order的值进行排序;也就是:PriorityOrdered asc,order值 asc

下面这几个都可以指定order的值 接口:org.springframework.core.Ordered,有个getOrder方法用来返回int类型的值 接口:org.springframework.core.PriorityOrdered,继承了Ordered接口,所以也有getOrder方法 注解:org.springframework.core.annotation.Order,有个int类型的value参数指定Order的大小

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.AnnotatedTypeMetadata;
@Order(1) //@1
class Condition1 implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        System.out.println(this.getClass().getName());
        return true;
    }
}
class Condition2 implements Condition, Ordered { //@2
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        System.out.println(this.getClass().getName());
        return true;
    }
    @Override
    public int getOrder() { //@3
        return 0;
    }
}
class Condition3 implements Condition, PriorityOrdered { //@4
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        System.out.println(this.getClass().getName());
        return true;
    }
    @Override
    public int getOrder() {
        return 1000;
    }
}
@Configuration
@Conditional({Condition1.class, Condition2.class, Condition3.class})//@5
public class MainConfig6 {
}
  • @1:Condition1通过@Order指定顺序,值为1
  • @2:Condition2通过实现了Ordered接口来指定顺序,
  • @3:getOrder方法返回1
  • @4:Condition3实现了PriorityOrdered接口,实现这个接口需要重写getOrder方法,返回1000
  • @5:Condtion顺序为1、2、3

ConfigurationCondition使用

ConfigurationCondition使用的比较少,很多地方对这个基本上也不会去介绍,Condition接口基本上可以满足99%的需求了,但是springboot中却大量用到了ConfigurationCondition这个接口。

ConfigurationCondition通过解释比较难理解,来个案例感受一下:

来一个普通的类:Service

 public class Service {
}

来一个配置类,通过配置类注册上面这个Service

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfig1 {
    @Bean
    public Service service() {
        return new Service();
    }
}

再来一个配置类:BeanConfig2

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfig2 {
    @Bean
    public String name() {
        return "路人甲Java";
    }
}

来一个总的配置类

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({BeanConfig1.class, BeanConfig2.class})
public class MainConfig7 {
}

现在我们有个需求

当容器中有Service这种类型的bean的时候,BeanConfig2才生效。

很简单吧,加个Condition就行了,内部判断容器中是否有Service类型的bean,继续

来个自定义的Condition

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class MyCondition1 implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取spring容器
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //判断容器中是否存在Service类型的bean
        boolean existsService = !beanFactory.getBeansOfType(Service.class).isEmpty();
        return existsService;
    }
}

上面代码很简单,判断容器中是否有IService类型的bean。

@Configuration
@Conditional(MyCondition1.class)
public class BeanConfig2 {
    @Bean
    public String name() {
        return "路人甲Java";
    }
}

结果name永远注册不上

为什么? 在文章前面我们说过,配置类的处理会依次经过2个阶段:配置类解析阶段和bean注册阶段,Condition接口类型的条件会对这两个阶段都有效,解析阶段的时候,容器中是还没有Service这个bean的,配置类中通过@Bean注解定义的bean在bean注册阶段才会被注册到spring容器,所以BeanConfig2在解析阶段去容器中是看不到Service这个bean的,所以就被拒绝了。

此时我们需要用到ConfigurationCondition了,让条件判断在bean注册阶段才起效。

自定义一个ConfigurationCondition类

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class MyConfigurationCondition1 implements ConfigurationCondition {
    @Override
    public ConfigurationPhase getConfigurationPhase() {
        return ConfigurationPhase.REGISTER_BEAN; //@1
    }
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取spring容器
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //判断容器中是否存在Service类型的bean
        boolean existsService = !beanFactory.getBeansOfType(Service.class).isEmpty();
        return existsService;
    }
}
  • @1:指定条件在bean注册阶段,这个条件才有效 matches方法中的内容直接复制过来,判断规则不变

修改BeanConfig2的类容

将
@Conditional(MyCondition1.class)
替换为
@Conditional(MyConfigurationCondition1.class)

此时name这个bean被注入了。

可以再试试将BeanConfig1中service方法上面的@Bean去掉,此时Service就不会被注册到容器

判断bean存不存在的问题,通常会使用ConfigurationCondition这个接口,阶段为:REGISTER_BEAN,这样可以确保条件判断是在bean注册阶段执行的。

对springboot比较熟悉的,它里面有很多@Conditionxxx这样的注解,可以去看一下这些注解,很多都实现了ConfigurationCondition接口。

Spring中这块的源码 @Conditional注解是被下面这个类处理的

org.springframework.context.annotation.ConfigurationClassPostProcessor

总结

@Conditional注解可以标注在spring需要处理的对象上(配置类、@Bean方法),相当于加了个条件判断,通过判断的结果,让spring觉得是否要继续处理被这个注解标注的对象

spring处理配置类大致有2个过程:解析配置类、注册bean,这两个过程中都可以使用@Conditional来进行控制spring是否需要处理这个过程

Condition默认会对2个过程都有效

ConfigurationCondition控制得更细一些,可以控制到具体那个阶段使用条件判断

以上就是Spring @Conditional通过条件控制bean注册过程的详细内容,更多关于Spring @Conditional控制bean注册的资料请关注我们其它相关文章!

(0)

相关推荐

  • 浅析SpringBoot2底层注解@Conditional@ImportResource

    目录 SpringBoot2底层注解 一.@ImportResource 示例 二.@ImportResource SpringBoot2底层注解 一.@ImportResource @Conditional注解,是根据条件进行装配.满足了 Conditional 指定的条件,就进行组件的注入. 另外@Conditional是个根注解,在idea里使用 ctrl+H 可以打开它的结构. 可以看到有许多的派生注解,每个注解都代表着一种功能.比如: @ConditionalOnBean:当容器中存在

  • SpringBoot 实现自定义的 @ConditionalOnXXX 注解示例详解

    目录 实现一个自定义的 @Conditional 派生注解 Conditional 派生注解的类如何注入到 spring 容器 实现一个自定义的 @Conditional 派生注解 自定义一个注解,继承 @Conditional 注解 // 派生注解 @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) @Documented @Conditional(CustomConditi

  • 详解SpringBoot中@ConditionalOnClass注解的使用

    目录 一.@ConditionalOnClass注解初始 二.@ConditionalOnClass注解用法 1.使用value属性 2.使用name属性 三.@ConditionalOnClass是怎么实现的 四.总结 今天给大家带来的是springboot中的@ConditionalOnClass注解的用法.上次的@ConditionalOnBean注解还记得吗? 一.@ConditionalOnClass注解初始 看下@CodidtionalOnClass注解的定义, 需要注意的有两点,

  • springboot @ConditionalOnMissingBean注解的作用详解

    @ConditionalOnMissingBean,它是修饰bean的一个注解,主要实现的是,当你的bean被注册之后,如果而注册相同类型的bean,就不会成功,它会保证你的bean只有一个,即你的实例只有一个,当你注册多个相同的bean时,会出现异常,以此来告诉开发人员. 代码演示 @Component public class AutoConfig { @Bean public AConfig aConfig() { return new AConfig("lind"); } @B

  • SpringBoot注解@ConditionalOnClass底层源码实现

    目录 @ConditionalOnClass的底层源码实现 ConditionOutcome对象 ClassNameFilter.MISSING判断某类是否不存在 @ConditionalOnClass的底层源码实现 在SpringBoot中,支持了很多种条件注解,@ConditionalOnClass注解就是其中之一,而且及其重要,它主要是用来判断该注解所指定的某个类或某些类,是否在ClassPath中存在,如果存在则符合条件,如果不存在则不符合. @Target({ ElementType.

  • Spring Boot自动配置的原理及@Conditional条件注解

    目录 1 @SpringBootApplication自动配置原理 2 @Conditional系列条件注解 1 @SpringBootApplication自动配置原理 @SpringBootApplication是一个组合注解,主要由@ComponentScan.@SpringBootConfiguration.@EnableAutoConfiguration这三个注解组成.@EnableAutoConfiguration是Spring Boot实现自动配置的关键注解. @Component

  • Spring @Conditional通过条件控制bean注册过程

    目录 Spring对配置类的处理主要分为2个阶段 配置类解析阶段 bean注册阶段 Spring对配置类处理过程 源码位置 整个过程大致的过程 ConfigurationCondition接口 Conditional使用的3步骤 阻止配置类的处理 bean不存在的时候才注册 根据环境选择配置类 Condition指定优先级 ConfigurationCondition使用 自定义一个ConfigurationCondition类 总结 Spring对配置类的处理主要分为2个阶段 配置类解析阶段

  • Spring IOC源码之bean的注册过程讲解

    目录 BeanDefition加载注册过程 进入obtainFreshBeanFactory方法 ​进入AbstractRefreshableApplicationContext类中的refreshBeanFactory方法 进入AbstractXmlApplicationContext类的loadBeanDefinitions方法 进入doLoadBeanDefinitions方法 Spring IoC--Bean的创建和初始化 Spring介绍 IoC介绍 IoC是什么 IoC能做什么 源码

  • 使用Spring @DependsOn控制bean加载顺序的实例

    spring容器载入bean顺序是不确定的,spring框架没有约定特定顺序逻辑规范.但spring保证如果A依赖B(如beanA中有@Autowired B的变量),那么B将先于A被加载.但如果beanA不直接依赖B,我们如何让B仍先加载呢? 控制bean初始化顺序 可能有些场景中,bean A 间接依赖 bean B.如Bean B应该需要更新一些全局缓存,可能通过单例模式实现且没有在spring容器注册,bean A需要使用该缓存:因此,如果bean B没有准备好,bean A无法访问.

  • 一文详解Spring如何控制Bean注入的顺序

    目录 简介 构造方法依赖(推荐) @DependsOn(不推荐) BeanPostProcessor(不推荐) 简介 说明 本文介绍Spring如何控制Bean注入的顺序. 首先需要说明的是:在Bean上加@Order(xxx)是无法控制bean注入的顺序的! 控制bean的加载顺序的方法 1.构造方法依赖 2.@DependsOn 注解 3.BeanPostProcessor 扩展 Bean初始化顺序与类加载顺序基本一致:静态变量/语句块=> 实例变量或初始化语句块=> 构造方法=>

  • Spring @Conditional注解示例详细讲解

    目录 前言: 示例: 标注在方法上: 标注在类上: 多个条件类: 前言: @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean. @Conditional的定义: //此注解可以标注在类和方法上 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Conditi

  • Spring @Conditional注解原理解析

    这篇文章主要介绍了Spring @Conditional注解原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 @Conditional是Spring4新提供的注解,它的作用是根据某个条件加载特定的bean. 我们需要创建实现类来实现Condition接口,这是Condition的源码 public interface Condition { boolean matches(ConditionContext var1, AnnotatedT

  • Spring为IOC容器注入Bean的五种方式详解

    这篇文章主要介绍了Spring为IOC容器注入Bean的五种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 @Import导入组件,id默认是组件的全类名 //类中组件统一设置.满足当前条件,这个类中配置的所有bean注册才能生效: @Conditional({WindowsCondition.class}) @Configuration @Import({Color.class,Red.class,MyImportSelector

  • spring @Conditional的使用与扩展源码分析

    目录 @Conditional的使用 WindowsCondition LinuxCondition Conditional的扩展 ConditionalOnBean ConditionalOnProperty 源码分析 @Conditional的使用 @Conditional可以根据条件来判断是否注入某些Bean. package com.morris.spring.config; import com.morris.spring.condition.LinuxCondition; impor

  • Spring示例讲解条件注入方法

    目录 简介 @Component+条件注解 @Configuration+@Bean+条件注解 @Configuration+条件注解+@Bean 自定义Condition 简介 说明 本文用实例介绍Spring的条件注入的用法. @Component.@Configuration+@Bean都可以与条件注入的注解结合. @Component+条件注解 Bean package com.example.config; import org.springframework.boot.autocon

  • Spring循环依赖正确性及Bean注入的顺序关系详解

    一.前言 我们知道 Spring 可以是懒加载的,就是当真正使用到 Bean 的时候才实例化 Bean.当然也不全是这样,例如配置 Bean 的 lazy-init 属性,可以控制 Spring 的加载时机.现在机器的性能.内存等都比较高,基本上也不使用懒加载,在容器启动时候来加载bean,启动时间稍微长一点儿,这样在实际获取 bean 供业务使用时,就可以减轻不少负担,这个后面再做分析. 我们使用到 Bean 的时候,最直接的方式就是从 Factroy 中获取,这个就是加载 Bean 实例的源

随机推荐