Spring Boot学习教程-----6.springboot的容器功能

2.容器功能

   2.1组件添加

    1. @Configuration(告诉springboot这是一个配置类==配置文件)

        1)基本模式

           Full模式和Lite模式

                 示例

                 最佳实践:

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

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

     实际案例,新建两个实体类,Pet和User,User依赖了Pet

Pet类

package com.ch.boot.bean;

public class Pet {
    public Pet() {
    }

    public Pet(String name) {
        this.name = name;
    }

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Pet{" +
                "name='" + name + '\'' +
                '}';
    }
}

 User类

package com.ch.boot.bean;

public class User {
    private String name;
    private  int age;
    private Pet pet;
    
    public User() {
    }
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Pet getPet() {
        return pet;
    }

    public void setPet(Pet pet) {
        this.pet = pet;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", pet=" + pet +
                '}';
    }
}

 再创建一个配置类,

package com.ch.boot.config;

import com.ch.boot.bean.Pet;
import com.ch.boot.bean.User;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/*
1.配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的
2.配置类本身也是一个组件
3.proxyBeanMethods:代理bean的方法
Full(proxyBeanMethods = true) 全量模式
lite(proxyBeanMethods = false) 轻量模式
组件依赖
* */
@Configuration(proxyBeanMethods = true)//告诉springboot这是一个配置类==配置文件
public class MyConfig {

    @Bean //给容器中添加组件  以方法名作为组件的id,
    // 返回类型就是组件类型,返回的只,就是组件在容器中的实例
    //外部无论对配置类中的组件注册方法调用多少遍,获取的都是之前注册容器中的单实例
    public User user01() {
        User zhansan = new User("zhansan", 18);
        //user组件依赖了pet组件
        zhansan.setPet(tomcatPet());
       return  zhansan;
    }

    @Bean("tom")
    public Pet tomcatPet() {
        return new Pet("tomcat");
    }

    // Pet tom=ru
}

     接下来是在主运行程序中,调用相关组件

package com.ch.boot;

import com.ch.boot.bean.Pet;
import com.ch.boot.bean.User;
import com.ch.boot.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

/*
主程序类,所有启动的入口
@SpringBootApplication:这是一个springboot应用
*/
@SpringBootApplication
public class MainApplication {

    public static void main(String[] args) {

        //返回我们的IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

        String[] names = run.getBeanDefinitionNames();
        for (String name:names) {
         System.out.println(""+name);
        }

        Pet tom01=run.getBean("tom",Pet.class);
        Pet tom02=run.getBean("tom",Pet.class);
        System.out.println("组件:"+(tom01==tom02));

        //com.ch.boot.config.MyConfig$$EnhancerBySpringCGLIB$$c1085e98@4a699efa
        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);
        User user01 = run.getBean(User.class);

        Pet tom=run.getBean("tom",Pet.class);
        System.out.println("用户中的宠物"+(user.getPet()==tom));
    }
}
proxyBeanMethods:代理bean的方法,当proxyBeanMethods = true时,运行结果如下,返回的组件都是单实例的,因为springboot会检查容器中是否存在该组件,有则调用,无则生成

组件:true
com.ch.boot.config.MyConfig$$EnhancerBySpringCGLIB$$bf8f635b@1136b469
true
用户中的宠物t

 proxyBeanMethods:代理bean的方法,当proxyBeanMethods =false时,运行结果如下,返回的组件都是多实例,每次生成组件都会new一个

组件:true
com.ch.boot.config.MyConfig@65327f5
false
用户中的宠物false

如果只是给容器中注册组件,其他组件也不依赖这些组件,那么就用false轻量模式,启动和加载会比较快;

如果组件被依赖,那么就是用true全量模式

    2.  @Bean,@Component(组件),@Controller(控制器),@Service(业务逻辑组件),@Repository(数据库层组件)

    3.@ComponentScan(包扫描),

   @Import(导入组件)

  @Import({User.class, DBHelper.class})

给容器中自动创建出这两个类型的组件,默认组件的名字就是全类名
String[] beanNamesForType = run.getBeanNamesForType(User.class);
System.out.println("==========");
for (String name2 : beanNamesForType) {
   System.out.println("user类型的组件名字"+name2);
}
DBHelper bean1 = run.getBean(DBHelper.class);
System.out.println("=========="+bean1);

测试结果如下:

user类型的组件名字com.ch.boot.bean.User
user类型的组件名字user01
==========ch.qos.logback.core.db.DBHelper@4905c46b

    4.@Conditional      

    条件装配,满足@Conditional指定的条件,才进行组件注入,ctrl+n查找类,ctrl+h打开继承树

派生注解:

@ConditionalOnBean,容器中存在指定的组件是,才做什么

@ConditionalOnMissBean,容器中不存在指定的组件,才做什么

@ConditionalOnClass,容器中存在指定的类,才做什么,

@ConditionalOnMissingClass,容器中不存在某些指定的类,才做什么

@ConditionalOnResource,容器类路径中存在某些指定的资源,才做什么

@ConditionalOnJava,指定某个Java版本号,才做什么

@ConditionalOnWebApplication,当应用是web应用的时候,才做什么

@ConditionalOnNotWebApplication,当应用不是web应用的时候,才做什么

案例,原先的配置类修改成这样,注解掉tom组件

package com.ch.boot.config;

import ch.qos.logback.core.db.DBHelper;
import com.ch.boot.bean.Pet;
import com.ch.boot.bean.User;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;


/*
1.配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的
2.配置类本身也是一个组件
3.proxyBeanMethods:代理bean的方法
Full(proxyBeanMethods = true) 全量模式
lite(proxyBeanMethods = false) 轻量模式
组件依赖

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

    @Bean //给容器中添加组件  以方法名作为组件的id,
    // 返回类型就是组件类型,返回的只,就是组件在容器中的实例
    //外部无论对配置类中的组件注册方法调用多少遍,获取的都是之前注册容器中的单实例
    public User user01() {
        User zhansan = new User("zhansan", 18);
        //user组件依赖了pet组件
        zhansan.setPet(tomcatPet());
       return  zhansan;
    }

  //  @Bean("tom")
    public Pet tomcatPet() {
        return new Pet("tomcat");
    }

    // Pet tom=ru
}

MainApplication中加入以下测试代码

  boolean tome=run.containsBean("tom");
        System.out.println("容器中Tom组件"+tome);

        boolean user01=run.containsBean("user01");
        System.out.println("容器中user组件"+user01);

结果如下

容器中Tom组件false
容器中user组件true

然后尝试给MyConfig中的User组件加入以下注解

@ConditionalOnBean(name="tom")

再运行,结果如下

容器中Tom组件false
容器中user组件false

  因为条件中必须含有名为“tom”的组件,才会注入组件User

2)@ConditionalOnBean(name="tom")加在类上,结果都不存在tom和user组件,因为这个条件必须成立,类里面的组件才会都执行,否则都不添加组件

3)当条件装配改成ConditionalOnMissBean(name="tom"),然后MyConfig的Pet容器的名称改为tom22,执行上面程序,结果是都存在user01和tom都存在,因为满足了条件装配,不存在组件tom,故生成组件user01和tom22

2.2原生配置文件的引入

1.@ImportResource(导入资源文件)

在Resource目录下新建一个配置文件,beans.xml的spring配置文件

<?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.ch.boot.bean.User">
        <property name="name" value="zhangsan"></property>
        <property name="age" value="18"></property>
    </bean>

    <bean id="hehe" class="com.ch.boot.bean.Pet">
        <property name="name" value="tomcat"></property>
    </bean>
</beans>

在MainApplication中测试

boolean haha=run.containsBean("haha");
boolean hehe=run.containsBean("hehe");
System.out.println("hahah"+haha);
System.out.println("hehe"+hehe);

结果

hahahfalse
hehefalse

 容器中没有这两个组件,然后在MyConfig类中引入资源文件

再次运行得到结果

hahahtrue
hehetrue

2.3配置管理

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

1)使用@ConfigurationProperties+@Component注解进行绑定,以下prefix是前缀,在配置文件中寻找所有前缀为mycar的配置绑定Car中,

创建一个car类来测试注解
package com.ch.boot.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/*
只有在容器中的组件,才拥有在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 +
                '}';
    }
}


Controller中加入测试

package com.ch.boot.controller;

import com.ch.boot.bean.Car;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/*@ResponseBody:代表直接写给浏览器,而不是跳转到某个页面
@Controller*
RestController :是上面两个注解的合体
/
 */
@RestController
public class HelloController {

    @Autowired
    Car car;

    @RequestMapping("/hello")
    public String handler01() {
        return "Hello Spring boot"+"中文";
    }

    @RequestMapping("/car")
    public Car car(){
        return car;
    }

}

结果如下,成功绑定

2)第二种资源配置方式@ConfigurationProperties+@EnableConfigurationProperties(必须在配置里面配置)

运行结果跟上面1)的结果一样

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值