SpringBoot2——容器功能

本篇文章将学习SpringBoot2中的容器功能,何为容器呢?

在学习Spring时有讲过IOC容器,Spring会帮我们创建好对象存储在IOC容器中,这也是创建对象的另一种方式

组件添加

1、@Configuration

@Configuration的作用是告诉SpringBoot这是一个配置类,相当于Spring中的xml配置文件,在xml配置文件中注入对象的属性,Spring帮我们自动创建对象并存入IOC容器中

先来看一下@Configuration的使用方法,配合@Bean来使用,@Bean以方法名作为组件id,如果希望自定义可以使用@Bean(“xxx”)

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

还是来看我们的主程序

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        //返回ioc容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class);
        //查看容器中的组件
        String[] beanDefinitionNames = run.getBeanDefinitionNames();
        for (String name:beanDefinitionNames) {
            System.out.println(name);
        }
        //获取容器中的组件
        /*
        如果@Configuration(proxyBeanMethods = true)代理对象调用方法
            springboot总会检查这个容器中是否存在组件,保持组件单实例
        如果@Configuration(proxyBeanMethods = false)创建的MyConfig对象就不再是一个代理对象
         */
        Person tom1 = run.getBean("tom", Person.class);
        Person tom2 = run.getBean("tom", Person.class);
        System.out.println("判断是否为单实例:" + (tom1 == tom2)); //true

        //com.yellowstar.boot.config.MyConfig$$EnhancerBySpringCGLIB$$76dd3309@27e32fe4
        MyConfig bean = run.getBean(MyConfig.class);
        System.out.println(bean);
        
        Pet cat1 = bean.cat();
        Pet cat2 = bean.cat();
        System.out.println("宠物:" + (cat1==cat2) ); //true
    }
}

下面有一个重点知识需要掌握,SpringBoot2中的@Configuration和SpringBoot相比,多了一个属性proxyBeanMethods,大致意思为是否创建一个代理类默认值为true,保证每个@Bean方法被调用多少次返回的组件都是单实例的,所以测试的返回值为true,将他设置为false来看一下

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        //返回ioc容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class);
        //查看容器中的组件
        String[] beanDefinitionNames = run.getBeanDefinitionNames();
        for (String name:beanDefinitionNames) {
            System.out.println(name);
        }
        //获取容器中的组件
        Person tom1 = run.getBean("tom", Person.class);
        Person tom2 = run.getBean("tom", Person.class);
        System.out.println("判断是否为单实例:" + (tom1 == tom2)); 
        //com.yellowstar.boot.config.MyConfig@4a31c2ee   已经不是一个代理对象了
        MyConfig bean = run.getBean(MyConfig.class);
        System.out.println(bean);

        Pet cat1 = bean.cat();
        Pet cat2 = bean.cat();
        System.out.println("宠物:" + (cat1==cat2) ); //false
    }
}

2、@Bean、@Component、@Controller、@Service、@Repository

这几个Spring中常用的注解,也延伸到了SpringBoot中,是可以正常使用的,这里不做过多介绍

3、@ComponentScan、@Import

@ComponentScan定义扫描注解的范围

@Import来重点认识一下,@Import给容器中自动创建两个类型的组件,默认组件名称为全类名,我们将其定义在MyConfig类上,其属性为我们需要注入到IOC容器中的对象类型

@Import({Person.class,Pet.class}) //给容器中自动创建两个类型的组件,默认组件名称为全类名
@Configuration(proxyBeanMethods = false) //告诉springboot这是这是一个配置类
public class MyConfig {
}

看一下控制台输出,发现这两个类型已经被注入到IOC容器中了,并且组件名称为全类名

在这里插入图片描述

4、@Conditional

条件装配,这个需要重点关注一下,在之后学习源码时,会经常见到他,标注在类或方法上,如果满足条件才执行此方法或类注入IOC容器。@Conditional衍生了非常多的子类

在这里插入图片描述

举例介绍@ConditionalOnBean,如果存在满足条件的组件,则执行方法

细心的同学会发现,我将cat组件的顺序排到了tom组件之前,这也是小黄在实操过程中发现的,如果按照原先顺序,因为在执行tom方法前ioc容器中并没有cat组件,所以不会注入tom组件

@Configuration(proxyBeanMethods = false) //告诉springboot这是这是一个配置类
@ImportResource("classpath:bean.xml")  //根据xml文件自动创建两个类型的组件
public class MyConfig {
    @Bean
    public Pet cat(){
        return new Pet("tomcat");
    }
    @Bean //给容器添加组件,以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
    @ConditionalOnBean( name = "cat") //有加载顺序,必须要在执行注解标注方法之前存在名为cat的组件,标注在类上必须要在加载该类之前存在cat组件
    public Person tom(){
        Person tom = new Person(1, "Tom");
        return tom;
    }
}
@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        //返回ioc容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class);
        //containsBean("xxx")查看容器中是否存在名为xxx的组件
        boolean cat = run.containsBean("cat");
        System.out.println("容器中cat组件:" + cat);
        boolean tom = run.containsBean("tom");
        System.out.println("容器中tom组件:" + tom);
    }
}

原生配置文件引入

在实际项目中会出现以下这种情况:该项目之前都是用SSM框架构建的,项目中配置了大量的xml文件来注入bean,现要使用SpringBoot来改造该项目,即使是维护这些Bean也需要大量的时间,那么SpringBoot为我们提供了另外一个注解,可以让我们引入原生的配置文件

@ImportResource

先来创建原生的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="make" class="com.yellowstar.boot.bean.Person">
        <property name="id" value="1"></property>
        <property name="name" value="make"></property>
    </bean>

    <bean id="tiger" class="com.yellowstar.boot.bean.Pet">
        <property name="name" value="tiger"></property>
    </bean>
</beans>

在MyConfig类上标注@ImportResource注解,这时候我们在运行主程序会发现这两个组件已经被存储到IOC容器中了

@Configuration(proxyBeanMethods = false) //告诉springboot这是这是一个配置类
@ImportResource("classpath:bean.xml")  //根据xml文件自动创建两个类型的组件
public class MyConfig {
}

在这里插入图片描述

配置绑定

如何使用Java读取到properties文件中的内容,并且封装到JavaBean中,这里我们就引入一个配置绑定的概念

创建一个Car类,我们希望自动注入ioc容器并且引用外部文件来配置该类的属性

public class Car {
    private String brand;
    private Integer price;
	//基本方法省略
}

application.properties配置文件

mycar.brand=BYD
mycar.price=100000

我们介绍以下两种方法

1、@Component + @ConfigurationProperties

@Component,被改注解标识的类会被注入IOC容器

@ConfigurationProperties,该注解有一个prefix属性,通过指定的前缀,绑定配置文件中的配置,该注解可以放在类上,也可以放在方法上

@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
    private String brand;
    private Integer price;
}

通过自动装配获取car看一下car的属性,此时就做到了配置绑定

@Controller
@ResponseBody
public class HelloController {
    @Autowired
    Car car;
    @RequestMapping("/car")
    public Car getCar(){
        System.out.println(car); //Car{brand='BYD', price=100000}
        return car;
    }
}

2、@EnableConfigurationProperties + @ConfigurationProperties

@EnableConfigurationProperties替换@Component,标识在配置类上,开启car的配置绑定功能,并把car组件注入到IOC容器中,还是执行以上方法,发现输出结果一样

@EnableConfigurationProperties(Car.class)
public class MyConfig {}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值