原创

@Configuration


@Configuration

**@Configuration告诉springboot这是一个配置类==配置文件 ** 在以往的spring中如果要将一个组件添加到容器里,需要xml进行bean的配置。现在我们只需要@Configuration和@Bean进行使用即可,举例:声明user和pet实体类和一个MyConfig配置类


public class user {
    private Integer age;
    private String name;

    public user() {
    }

    public user(Integer age, String name) {
        this.age = age;
        this.name = name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

package com.zjh.boot.bean;

public class pet {
    private String name;

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

    public pet() {
    }

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

    public String getName() {
        return name;
    }

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

package com.zjh.boot.config;

import com.zjh.boot.bean.pet;
import com.zjh.boot.bean.user;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)//告诉springboot这是一个配置类==配置文件
//proxyBeanMethods:代理bean的方法 默认为true
//配置类其实也是一个组件
public class MyConfig {
    @Bean//给容器添加组件 以方法名作为组件id,返回类型就是组件类型,返回的值就是组件在容器里的实例
    //可以在bean注解里添加组件的名字
    //组件默认是单实例的
    public user getUser01(){
        return new user(20,"张家豪");
    }
    @Bean
    public pet getPet01(){
        return new pet("tomcat");
    }

    /*
    *
    * 外部无论对配置类中的这个组件注册方法调用多少次获取的都是注册容器中的那个对象*/
}

把MyConfig类加入@Configuration注解,在里面声明两个方法来获取user和pet对象,并在方法上加入@Bean
@Bean 给容器添加组件 以方法名作为组件id,返回类型就是组件类型,返回的值就是组件在容器里的实例,可以在bean注解里添加组件的名字 我们在springboot的启动类里可以查看到添加进去的组件

@SpringBootApplication
public class MainApplication {
    public static void main(String []args){
        //1:返回IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
        //2:查看容器里面的组件
        String[] beanDefinitionNames = run.getBeanDefinitionNames();
        //依次遍历
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
	}

我们可以从容器里获取组件

user user01 = run.getBean("getUser01", user.class);
        user user02 = run.getBean("getUser01",user.class);
        System.out.println("查看是不是单实例"+(user01 == user02));

结果得知是单实例的


@Configuration注解里有一个proxyBeanMethods属性,默认为true。(代理bean的方法) 在proxyBeanMethods默认为true的情况下,我们获取配置类对象,调用里面的获取pet对象的方法

      MyConfig bean = run.getBean(MyConfig.class);
	          pet pet01 = bean.getPet01();
        pet pet011 = bean.getPet01();
        System.out.println(pet01==pet011);
        System.out.println(pet01);

由结果可以得知获取的两个pet对象是同一个对象。即外部无论对配置类中的这个组件注册方法调用多少次获取的都是注册容器中的那个对象

如果将proxyBeanMethods默认改为false 则两个pet对象不是同一个对象。


现在我们在user类里面声明一个pet对象

package com.zjh.boot.bean;

public class user {
    private Integer age;
    private String name;
    private pet pet;
    public user() {
    }

    public user(Integer age, String name) {
        this.age = age;
        this.name = name;
    }

    public user(Integer age, String name, com.zjh.boot.bean.pet pet) {
        this.age = age;
        this.name = name;
        this.pet = pet;
    }

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

    public com.zjh.boot.bean.pet getPet() {
        return pet;
    }

    public void setPet(com.zjh.boot.bean.pet pet) {
        this.pet = pet;
    }

    public Integer getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

在配置类里定义

@Configuration(proxyBeanMethods = true)//告诉springboot这是一个配置类==配置文件
//proxyBeanMethods:代理bean的方法 默认为true
//配置类其实也是一个组件
public class MyConfig {
    @Bean//给容器添加组件 以方法名作为组件id,返回类型就是组件类型,返回的值就是组件在容器里的实例
    //可以在bean注解里添加组件的名字
    //组件默认是单实例的
    public user getUser01(){
        user user = new user(20, "张家豪");
        user.setPet(getPet01());
        return user;
    }
    @Bean
    public pet getPet01(){
        return new pet("tomcat");
    }

    /*
    *
    * 外部无论对配置类中的这个组件注册方法调用多少次获取的都是注册容器中的那个对象*/
}

现在我们相当于在容器里注册一个user组件和pet组件,但是我们的user组件里的pet属性想要是pet组件,如果proxyBeanMethods默认为true的情况下

    user user01 = run.getBean("getUser01", user.class);
	MyConfig bean = run.getBean(MyConfig.class);
    pet pet01 = bean.getPet01();
	pet pet = user01.getPet();
    System.out.println(pet01==pet);
		

可以得到结果为true。即user组件依赖了pet组件,称为组件依赖 如果proxyBeanMethods为false,则结果为false。 我们将proxyBeanMethods调成false,即我们在外部调用配置类的方法时,springboot不会检查返回的对象在容器中是否存在,就会直接创建,springboot启动速度会变快,proxyBeanMethods调成true则反之。


最佳实战: 1:类组件之间无依赖关系用Lite模式(proxyBeanMethods==false)加速容器启动过程,减少判断 2:类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式(proxyBeanMethods==true)

留言