SpringBoot Bean被加载时进行控制

 更新时间:2023年02月10日 09:29:58   作者:零维展开智子  
很多时候我们需要根据不同的条件在容器中加载不同的Bean,或者根据不同的条件来选择是否在容器中加载某个Bean,这就是Bean的加载控制,一般我们可以通过编程式或注解式两种不同的方式来完成Bean的加载控制

序章

简介:bean的加载控制指根据特定情况对bean进行选择性加载以达到适用项目的目标。

根据之前对bean加载的八种方式,其中后面四种是可以对bean被加载时进行控制。

我拿第六种来举个例子。

之前也举过例子,但是实际开发呢,一般不会那么使用。

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        try {
            Class<?> name = Class.forName("yi.beans.kun");
            if (name!=null){
                return new String[]{"yi.beans.Cat"};
            }
        }catch (ClassNotFoundException e){
            return new  String[0];
        }
        return null;
    }
}

通过查看某个类是否存在来控制是否加载目标类。

这个类我是不存在的。

import org.springframework.context.annotation.Import;
import yi.beans.MyImportSelector;
@Import(MyImportSelector.class)
public class AConfig {
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import yi.config.AConfig;
public class App3 {
    public static void main(String[] args) {
        ApplicationContext context=new AnnotationConfigApplicationContext(AConfig.class);
        String[] names = context.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
    }
}

所以我是没有加载这个bean的,还是老话,前面的那些暂时不看。

加载控制@Conditional派生注解

到了这里,你的spring项目就该换成springboot项目了,pom.xml中添加坐标,我就不多说了,这就是springboot的注解,源代码中大量使用。

这是我未加控制前的代码

import org.springframework.context.annotation.ComponentScan;
@ComponentScan("yi.beans")
public class AConfig {
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import yi.config.AConfig;
public class App3 {
    public static void main(String[] args) {
        ApplicationContext context=new AnnotationConfigApplicationContext(AConfig.class);
        String[] names = context.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
    }
}

有猫,有狗,有老鼠,只不过我给他们都起了名字,你们很容易就会看出来。

现在我要对猫这个bean在创建时加一控制。

控制后

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication;
import org.springframework.stereotype.Component;
@ConditionalOnClass(Mouse.class)    //要加载猫,必须要有老鼠这个bean
@ConditionalOnBean(name = "zhizhi")     //而且这个老鼠bean的名字必须是“zhizhi”
@ConditionalOnMissingClass("yi.beans.Dog")      //但是不能有狗,猫捉老鼠不想有狗
@ConditionalOnNotWebApplication     //环境必须为非Web环境
@Component("miao")  //猫的bean叫“miao”
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Cat {
    String shout;
}

这里我加了几个常见的派生注解,其他的代码都是不用变的,我的bean里卖虽然有一个叫做“zhizhi”的老鼠,但是有狗,所以猫是加载不出来的。

其中的

@ConditionalOnClass
@ConditionalOnBean

这两个注解非常相似,一般就用上面那个控制类的字节码或者路径。下面那个获取bean的名字,搭配使用就好了。

bean依赖的属性配置

先定义两个最基础的bean

import lombok.Data;
@Data
public class Mouse {
    private String name;
    private int age;
}
import lombok.Data;
@Data
public class Cat {
    private String name;
    private int age;
}

cartoon:
  cat:
    name: "图多盖洛"
    age:  5
  mouse:
    name: "泰菲"
    age: 1 

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "cartoon")    
public class CartoonProperties {
    private Cat cat;
    private Mouse mouse;
}
import lombok.Data;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Data
@Component
@EnableConfigurationProperties(CartoonProperties.class)
public class CartoonCatAndMouse {
    private Cat cat;
    private Mouse mouse;
    private CartoonProperties cartoonProperties;
    public CartoonCatAndMouse(CartoonProperties cartoonProperties){
        this.cartoonProperties=cartoonProperties;
        this.cat=new Cat();
        this.cat.setName(cartoonProperties.getCat()!=null&& StringUtils.hasText(cartoonProperties.getCat().getName())?
                cartoonProperties.getCat().getName():"Tom");
        this.cat.setAge(cartoonProperties.getCat()!=null&& cartoonProperties.getCat().getAge()!=0?
                cartoonProperties.getCat().getAge():6);
        this.mouse=new Mouse();
        this.mouse.setName(cartoonProperties.getMouse()!=null&&StringUtils.hasText(cartoonProperties.getMouse().getName())?
                cartoonProperties.getMouse().getName():"Jerry");
        this.mouse.setAge(cartoonProperties.getMouse()!=null && cartoonProperties.getMouse().getAge()!=0?
                cartoonProperties.getMouse().getAge():2);
    }
    public void play() {
        System.out.println(cat.getAge()+"岁的"+cat.getName()+"和"+mouse.getAge()+"岁的"+mouse.getName()+"打起来了");
    }
}
import com.yi.bean.CartoonCatAndMouse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringbootBean2ApplicationTests {
    @Autowired
    private CartoonCatAndMouse cartoonCatAndMouse;
    @Test
    void contextLoads() {
        cartoonCatAndMouse.play();
    }
}

可以看到加载的就是我们自己写的配置,现在我把配置注解一部分,我们再来看运行结果。

cartoon:
  cat:
#    name: "图多盖洛"
    age:  5
  mouse:
#    name: "泰菲"
    age: 1

可以看到,没有写的属性使用的就是默认属性,也就是自动配置的思想,只有在调用的时候才会生成bean,默认的bean也不会在项目加载时就添加,这样压力会很大。如果我们没有使用某个第三方的bean,我们的项目启动时也并不会加载默认的bean。

到此这篇关于SpringBoot Bean被加载时进行控制的文章就介绍到这了,更多相关SpringBoot Bean加载控制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot扫描引入jar包的service等组件方式

    springboot扫描引入jar包的service等组件方式

    这篇文章主要介绍了springboot扫描引入jar包的service等组件方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 如何利用Ganymed SSH-2模拟SSH操作

    如何利用Ganymed SSH-2模拟SSH操作

    这几天看SFTP资料时,无意中看到了Ganymed SSH-2,写了个简单demo,通过,感觉挺好用的,下面就和大家分享下。需要的朋友可以过来参考参考
    2013-08-08
  • RestTemplate如何添加请求头headers和请求体body

    RestTemplate如何添加请求头headers和请求体body

    这篇文章主要介绍了RestTemplate如何添加请求头headers和请求体body问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 关于Java中的IO流总结(推荐)

    关于Java中的IO流总结(推荐)

    下面小编就为大家带来一篇关于Java中的IO流总结(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • SpringBoot中的自定义Banner详细解析

    SpringBoot中的自定义Banner详细解析

    这篇文章主要介绍了SpringBoot中的自定义Banner详细解析,Banner即横幅标语,我们在启动SpringBoot项目时会将Banner信息打印至控制台,我们可以输出一些图形、SpringBoot版本信息等内容,需要的朋友可以参考下
    2024-01-01
  • java实现两个线程交替打印的实例代码

    java实现两个线程交替打印的实例代码

    在本篇文章里小编给大家整理的是一篇关于java实现两个线程交替打印的相关知识点内容,有需要的朋友们参考下。
    2019-12-12
  • Intellij idea 代码提示忽略字母大小写和常用快捷键及设置步骤

    Intellij idea 代码提示忽略字母大小写和常用快捷键及设置步骤

    这篇文章主要介绍了Intellij idea 代码提示忽略字母大小写和常用快捷键及设置步骤,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-02-02
  • SpringCloud启动eureka server后,没报错却不能访问管理页面(404问题)

    SpringCloud启动eureka server后,没报错却不能访问管理页面(404问题)

    这篇文章主要介绍了SpringCloud启动eureka server后,没报错却不能访问管理页面(404问题),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • Spring中@RabbitHandler和@RabbitListener的区别详析

    Spring中@RabbitHandler和@RabbitListener的区别详析

    @RabbitHandler是用于处理消息的方法注解,它与@RabbitListener注解一起使用,这篇文章主要给大家介绍了关于Spring中@RabbitHandler和@RabbitListener区别的相关资料,需要的朋友可以参考下
    2024-02-02
  • log4j的使用详细解析

    log4j的使用详细解析

    最近在整理公司产品的日志输出规范,涉及log4j的使用介绍,就简单整理了一下。需要的朋友可以过来参考参考
    2013-08-08

最新评论