SpringBoot 如何从容器中获取对象

目录
  • 如何从容器中获取对象
  • SpringBoot中的容器
    • 容器功能
      • 1、组件添加
      • 2、原生配置文件引入(xml文件引入)
      • 3、配置绑定

如何从容器中获取对象

有时候在项目中,我们会自己创建一些类,类中需要使用到容器中的一些类。方法是新建类并实现ApplicationContextAware 接口,在类中建立静态对象 ApplicationContext 对象,这个对象就如同xml配置中的 applicationContext.xml,容器中类都可以获取到。

例如@Service、 @Component、@Repository、@Controller 、@Bean 标注的类都能获取到。

/**
 * 功能描述:Spring Bean 管理类
 *
 */
@Component
public class SpringContextUtils implements ApplicationContextAware {
    /**
     * 上下文对象实例
     */
    private static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    /**
     * 获取applicationContext
     *
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    /**
     * 通过name获取 Bean.
     *
     * @param name
     * @return
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }
    /**
     * 通过class获取Bean.
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        try{
            return getApplicationContext().getBean(clazz);
        }catch (Exception e){
            return null;
        }
    }
    /**
     * 通过name,以及Clazz返回指定的Bean
     *
     * @param name
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}

SpringBoot中的容器

容器功能

1、组件添加

(1)主要注解

@Configuration

告诉SpringBoot这是一个配置类 == 配置文件

注意:spring5.2以后@Configuration多了一个属性proxyBeanMethods,默认为true

@Configuration(proxyBeanMethods = true)
  • proxyBeanMethods:代理bean的方法
  • Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】 外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
  • Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
  • 组件依赖必须使用Full模式默认。其他默认是否Lite模式

● Full模式与Lite模式

○ 最佳实战

■ 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断

■ 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式

@Bean

  • 给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
  • 配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的
  • 配置类本身也是组件

(2) 基本使用

bean包:

Pet类:

/**
 * 宠物
 */
public class Pet {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Pet(String name) {
        this.name = name;
    }
    public Pet() {
    }
    @Override
    public String toString() {
        return "Pet{" +
                "name='" + name + '\'' +
                '}';
    }
}

User类:

/*
用户
 */
public class User {
    private String name;
    private Integer age;
    public User() {
    }
    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

config包:

MyConfig类

@Configuration(proxyBeanMethods = false)//告诉Spring这是一个配置类
public class MyConfig {
    @Bean//给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
    public User user01(){
        return  new User("zhangsan",18);
    }
    @Bean("tom")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

controller包:

MainApplication类

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com")
public class MainApplication {
    public static void main(String[] args) {
        //1、返回我们IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
        //2、查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
        //3、从容器中获取组件
        MyConfig bean = run.getBean(MyConfig.class);
        System.out.println(bean);
        //如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。
        //保持组件单实例
        User user = bean.user01();
        User user1 = bean.user01();
        System.out.println("组件为:"+(user == user1));
    }
}

结果

(3)补充 @Import

给容器导入一个组件

必须写在容器中的组件上

 * @Import({User.class, DBHelper.class})
 *      给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
 *
 *
 *
 */
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
}

@Configuration测试代码如下

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com")
public class MainApplication {
    public static void main(String[] args) {
        //1、返回我们IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
        //2、查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
        //3、从容器中获取组件
        MyConfig bean = run.getBean(MyConfig.class);
        System.out.println(bean);
        //如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。
        //保持组件单实例
        User user = bean.user01();
        User user1 = bean.user01();
        System.out.println("组件为:"+(user == user1));
        //5、获取组件
        String[] beanNamesForType = run.getBeanNamesForType(User.class);
        System.out.println("======");
        for (String s : beanNamesForType) {
            System.out.println(s);
        }
        DBHelper bean1 = run.getBean(DBHelper.class);
        System.out.println(bean1);
    }
}

@Conditional

条件装配:满足Conditional指定的条件,则进行组件注入

  • ConditionalOnBean:当容器中存在指定的bean组件时才干某些事情
  • ConditionalOnMissingBean:当容器中不存在指定的bean组件时才干某些事情
  • ConditionalOnClass:当容器中有某个类时才干某些事情
  • ConditionalOnResource:当项目的类路径存在某个资源时,才干什么事
=====================测试条件装配==========================
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
//@ConditionalOnBean(name = "tom")
@ConditionalOnMissingBean(name = "tom")
public class MyConfig {
    @Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
    public User user01(){
        User zhangsan = new User("zhangsan", 18);
        //user组件依赖了Pet组件
        zhangsan.setPet(tomcatPet());
        return zhangsan;
    }
    @Bean("tom22")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

测试:

public static void main(String[] args) {
        //1、返回我们IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
        //2、查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
        boolean tom = run.containsBean("tom");
        System.out.println("容器中Tom组件:"+tom);
        boolean user01 = run.containsBean("user01");
        System.out.println("容器中user01组件:"+user01);
        boolean tom22 = run.containsBean("tom22");
        System.out.println("容器中tom22组件:"+tom22);
    }

2、原生配置文件引入(xml文件引入)

@ImportResource

导入资源

@ImportResource("classpath:beans.xml")//导入spring的配置文件
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false)//告诉Spring这是一个配置类
@ConditionalOnMissingBean(name = "tom")
public class MyConfig {
======================beans.xml=========================
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="haha" class="com.atguigu.boot.bean.User">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="18"></property>
    </bean>
    <bean id="hehe" class="com.atguigu.boot.bean.Pet">
        <property name="name" value="tomcat"></property>
    </bean>
</beans>

测试

======================测试=================
        boolean haha = run.containsBean("haha");
        boolean hehe = run.containsBean("hehe");
        System.out.println("haha:"+haha);//true
        System.out.println("hehe:"+hehe);//true

3、配置绑定

如何使用Java读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用;

(1) @Component + @ConfigurationProperties

properties文件

/**
 * 只有在容器中的组件,才会拥有SpringBoot提供的强大功能
 */
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
    private String brand;
    private Integer price;
    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public Integer getPrice() {
        return price;
    }
    public void setPrice(Integer price) {
        this.price = price;
    }
    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}

(2) @EnableConfigurationProperties + @ConfigurationProperties

@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
@ConditionalOnMissingBean(name = "tom")
@ImportResource("classpath:beans.xml")
//@EnableConfigurationProperties(Car.class)
//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
public class  MyConfig {

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java SpringBoot容器注入对象详解

    目录 1.注入的方式 方式一:使用Import注解 方式二:使用@Service 或者@Component等注解注入到容器中 方式三:使用@Configuration和@Bean组合实现 2.注入是增加条件判断注解 3.构造方法时带参数注入 方式1:使用spring xml实现 方式2:使用@Autowired 方式3使用@Configuration和@Bean组合 4.对象注入时的一些总结 总结 1.注入的方式 方式一:使用Import注解 增加一个类HelloCompent package

  • SpringBoot 嵌入式web容器的启动原理详解

    目录 SpringBoot应用启动run方法 SpringApplication.java 中执行的代码 ServletWebServerApplicationContext.java执行的方法 SpringBoot 2.x 版本 嵌入式Servlet容器自动配置原理以及启动原理 一.版本说明 二.总结 三.嵌入式Servlet容器自动配置原理(以Tomcat为例) 四.嵌入式Servlet容器启动原理(以Tomcat为例) SpringBoot应用启动run方法 SpringApplicati

  • 关于Springboot如何获取IOC容器

    目录 Springboot项目中获取IOC容器的方式 方法一(不实用,不推荐): 方法二(强烈推荐): 总结 Springboot项目中获取IOC容器的方式 在Springboot项目中如果要获取IOC容器目前有两种方法. 方法一(不实用,不推荐): 在Springboot项目中都会存在一个SpringApplication的启动类,我们通过以下代码启动IOC容器. SpringApplication.run(Application.class, args); 其实run方法会将创建的IOC容器

  • 学习SpringBoot容器功能及注解原理

    目录 1.组件添加 1.1@Configuration 1.2@Import 1.3@Conditional 2.原生配置文件引入 2.1@ImportResource 3.配置绑定 3.1@ConfigurationProperties 3.2@EnableConfigurationProperties + @ConfigurationProperties 1.组件添加 1.1@Configuration @Configuration:告诉SpringBoot这是一个配置类 配置类里面使用@B

  • SpringBoot 如何从容器中获取对象

    目录 如何从容器中获取对象 SpringBoot中的容器 容器功能 1.组件添加 2.原生配置文件引入(xml文件引入) 3.配置绑定 如何从容器中获取对象 有时候在项目中,我们会自己创建一些类,类中需要使用到容器中的一些类.方法是新建类并实现ApplicationContextAware 接口,在类中建立静态对象 ApplicationContext 对象,这个对象就如同xml配置中的 applicationContext.xml,容器中类都可以获取到. 例如@Service. @Compon

  • Java 如何从spring容器中获取注入的bean对象

    1.使用场景 控制层调用业务层时,控制层需要拿到业务层在spring容器中注入的对象 2.代码实现 import org.apache.struts2.ServletActionContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.suppo

  • SpringBoot如何在线程中获取@Service Bean类

    目录 如何在线程中获取@ServiceBean类 我们现在开始解决问题 多线程中获取bean对象 创建类 多线程中的调用方式 如何在线程中获取@Service Bean类 这个适用于没有Spring配置文件的Springboot项目中,有配置文件的话取bean就方便多了. 下图是我用@Service注解声明的一个Mybatis Mapper Bean,平常在Springboot扫描配置下的类直接用 @Autowired注解依赖注入. 我现在需要在线程中使用,然而Springboot自然而然只能扫

  • 基于Unity容器中的对象生存期管理分析

    IoC容器的对象生存期管理 如果你一直在使用IoC容器,你可能已经使用过了一些对象生存期管理模型(Object Lifetime Management).通过对对象生存期的管理,将使对象的复用成为可能.同时其使容器可以控制如何创建和管理对象实例. Unity提供的对象生存期管理模型是通过从抽象类LifetimeManager的派生类来完成.Unity将为每个类型的注册创建生存期管理器.每当UnityContainer需要创建一个新的对象实例时,将首先检测该对象类型的生存期管理器,是否已有一个对象

  • Javascript中获取对象的原型对象的方法小结

    在Javascript中,如果我们有一个对象但是又不知道它的构造函数时,如何获取它的原型对象呢? 在Chrome中或是FireFox浏览器中,我们可以直接使用对象的__proto__属性获取它的原型对象. 复制代码 代码如下: <!-- lang: js --> function F(){}; var foo = new F(); alert(foo.__proto__ == F.prototype); 但是,__proto__属性在IE浏览器中一直到IE11才被支持. 那么在不支持__pro

  • Python中获取对象信息的方法

    当我们拿到一个对象的引用时,如何知道这个对象是什么类型.有哪些方法呢? 使用type() 首先,我们来判断对象类型,使用type()函数: 基本类型都可以用type()判断: >>> type(123) <type 'int'> >>> type('str') <type 'str'> >>> type(None) <type 'NoneType'> 如果一个变量指向函数或者类,也可以用type()判断: >&

  • 普通对象使用spring容器中的对象的实现方法

    引语: 工作中有时候需要在普通的对象中去调用spring管理的对象,但是在普通的java对象直接使用@Autowired或者@Resource的时候会发现被注入的对象是null,会报空指针.我们可以简单的理解为spring是一个公司,它管理的对象就是它的员工,而普通的java对象是其他公司的员工,如果其他公司要找spring公司的员工一起共事没有经过spring公司的同意肯定是不行的. 解决方式: 方法一:如果这个普通对象可以被spring管理的话,最好是直接交给spring管理,这样sprin

  • Spring-IOC容器中的常用注解与使用方法详解

    Spring是什么? Spring是一个轻量级Java开发框架,最早有Rod Johnson创建,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题.它是一个分层的JavaSE/JavaEE full-stack(一站式)轻量级开源框架,为开发Java应用程序提供全面的基础架构支持.Spring负责基础架构,因此Java开发者可以专注于应用程序的开发. 体系结构 核心容器(Core Container):Spring的核心容器是其他模块建立的基础,有Spring-core.Spring

  • docker容器中无法获取宿主机hostname的解决方案

    在nodejs环境中测试通过,其它语言同理,只需要使用获取环境变量的方法即可. 思路: docker容器和宿主机环境是隔离的,但是可以在启动docker容器时将宿主机的主机名以环境变量的形式传入,代码在容器中获取该值即可. 操作: docker run -d -p 3000:3000 --name myTest -e HOST_Q=$(hostname) mytest:v1 # 使用-e 参数传入环境变量,值为主机名 如果使用yml文件启动: version: '3' services: mys

随机推荐