作用1:告诉springboot这是一个配置类,等同于之前在spring中的配置文件,而且配置类中可以使用@Bean标注在方法上给容器注册组件,该组件默认也是单例
创建pet:
package com.springboot.bean; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class Pet { private String name; }
创建User:
package com.springboot.bean; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class User { private String name; private Integer age; }
在spring中,我们将组件交给IOC容器进行管理是通过如下所示的配置文件:
<?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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--使用原始的方式进行,springboot不再沿用该方法--> <bean id="user01" class="com.springboot.bean.User"> <property name="name" value="张三"></property> <property name="age" value="18"></property> </bean> <bean id="MyPet" class="com.springboot.bean.Pet"> <property name="name" value="小猫"></property> </bean> </beans>
而在springboot中,我们可以通过在类上添加@Configuration注解,添加该注解的类被认为是一个配置类,会被IOC容器管理。@Configuration注解告诉Spring容器,该类是一个配置类,Spring会扫描该类中的@Bean注解,将其标记为一个Bean,并将其加入到IOC容器中进行管理。
如下所示:
package com.springboot; import com.springboot.bean.Pet; import com.springboot.bean.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyConfig { //@Bean表明添加组件,默认的是以方法名作为组件的id,返回类型就是组件类型,返回的值就是组件在容器中的实例对象 @Bean public User user01(){ return new User("张三",18); } //如果不想让方法名作为id,那么可以在@Bean中自定义名称,如下所示 @Bean("tom") public Pet MyPet(){ return new Pet("哈基米"); } }
下面我们可以在启动类中获取该组件,如下所示:
package com.springboot; import com.springboot.bean.Pet; import com.springboot.bean.User; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class MainApplication { public static void main(String[] args) { ConfigurableApplicationContext run= SpringApplication.run(MainApplication.class,args); //从容器中获取的每个组件都是单例的吗? //这里获取组件的方法和spring中的相同有三种方式: //1:通过类名 2:通过id 3:通过类名+id User user1=run.getBean("user01", User.class); User user2=run.getBean("user01",User.class); System.out.println(user1); System.out.println(user2); System.out.println(user1==user2); Pet pet1=run.getBean("tom", Pet.class); Pet pet2=run.getBean("tom", Pet.class); System.out.println(pet1); System.out.println(pet2); System.out.println(pet1==pet2); } }
输出如下所示:
User(name=张三, age=18) User(name=张三, age=18) true Pet(name=哈基米) Pet(name=哈基米) true
作用2:添加@Configuration的类被视为配置类,其配置类本身也是一个组件
既然它是组件,那么同样是交给IOC容器管理,我们同样可以通过IOC容器获取
MyConfig myConfig= run.getBean(MyConfig.class); System.out.println(myConfig);
输出如下所示:
com.springboot.MyConfig$$EnhancerBySpringCGLIB$$549b0910@347bdeef
作用三:该注解有个属性proxyBeanMethods,它的默认值如下所示是true
将该属性设置为true[Full模式],表明是代理对象调用方法,springboot总是会检查当前要调用的该组件是否在容器中已存在,只要存在,那么外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器的单实例对象,而将该属性设置为false[Lite模式],表明配置类在容器中再也不会保存代理类对象,因此在外部类进行调用时,每次调用都会产生一个新的对象
启动类:
package com.springboot; import com.springboot.bean.Pet; import com.springboot.bean.User; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class MainApplication { public static void main(String[] args) { ConfigurableApplicationContext run= SpringApplication.run(MainApplication.class,args); MyConfig myConfig= run.getBean(MyConfig.class); User user1=myConfig.user01(); User user2=myConfig.user01(); System.out.println(user1==user2);//输出true Pet pet1=myConfig.MyPet(); Pet pet2=myConfig.MyPet(); System.out.println(pet1==pet2);//输出true } }
那么到底是将其设置为false还是true呢?这取决于我们实际的需求,如果配置类组件之间没有依赖关系,那么我们将其设置为false,因为跳过了检查容器中是否有该对象的过程,加速了容器的启动过程,而配置类组件之间有依赖关系,我们应将其设置为true,因为方法会被调用得到之前单实例组件。