1.@Configuration注解
用法:作用在类上面
作用:告诉SpringBoot这是一个配置类,相当于Spring中的xml配置文件。
@Configuration //告诉SpringBoot这是一个配置类 == 配置文件
public class Config {
}
2.@bean注解
用法:配置类里面使用@Bean标注在方法上给IoC容器注册组件,默认也是单实例的
作用:给容器中添加组件,相当于Spring中xml配置文件中的<bean>标签。
理解:以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
@Configuration //告诉SpringBoot这是一个配置类 == 配置文件
public class Config {
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
public Person person1(){
return new Person("Mr.Yu",21,"male");
}
@Bean("customize") //id值也可以指定
public Person person2(){
return new Person("小明",20,"male");
}
}
在主程序类中打印输出我们IoC容器中的对象,看看我们的person1和customize有没有添加到容器中
@SpringBootApplication
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);
}
}
}
输出结果:
可以看到输出结果中有我们存放进IoC容器的两个对象
3.单实例
3.单实例
@Bean注解存入到IoC容器中的实例也是单实例的
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);
}
//单实例
Person person1 = run.getBean("person1",Person.class);
Person person2 = run.getBean("person1",Person.class);
System.out.println("person1 == person2 :"+ (person1 == person2));
}
输出结果:
4.配置类也是容器的组件
4.配置类也是容器的组件
@SpringBootApplication
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);
}
//配置类本身也是组件
Config bean = run.getBean(Config.class);
//com.ysw.boot.config.Config$$EnhancerBySpringCGLIB$$4aa44992@381d7219
System.out.println(bean);
}
}
输出结果:
com.ysw.boot.config.Config$$EnhancerBySpringCGLIB$$4aa44992@381d7219
5.直接调用配置类里面的person1()方法
5.直接调用配置类里面的person1()方法
如果我们直接调用配置类里面的person1()方法会发生什么情况,它是从IoC容器中拿还是直接new一个对象呢
在new一个配置类出来的情况下,调用person1方法,它返回的是new出来的对象但是如果我们从容器中取得的配置类,无论再去掉用多少次person1方法,它始终返回的都是同一个单实例对象,也就是从IoC容器中拿的对象。
@SpringBootApplication 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); } //配置类本身也是组件 Config bean = run.getBean(Config.class); //获取到的本身就是代理对象 //com.ysw.boot.config.Config$$EnhancerBySpringCGLIB$$4aa44992@381d7219 System.out.println(bean); //如果我们直接调用person1方法,它是从IoC容器中拿还是直接new一个对象呢, //在new一个配置类出来的情况下,调用person1方法,它返回的是new出来的对象 Config config = new Config(); Person person3 = config.person1(); Person person4 = config.person1(); System.out.println("person3 == person4 :"+ (person3 == person4)); //但是如果我们从容器中取得的配置类,无论再去掉用多少次person1方法,它始终返回的都是同一个单实例对象,也就是从IoC容器中拿的对象。 //如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有; //保持组件单实例 Person person5 = bean.person1(); Person person6 = bean.person1(); System.out.println("person5 == person6 :"+ (person5 == person6)); } }
输出结果:
6.proxyBeanMethods——代理bean的方法
6.proxyBeanMethods——代理bean的方法
从容器中获取到的配置类对象输出结果:
com.ysw.boot.config.Config$$EnhancerBySpringCGLIB$$4aa44992@381d7219
在上述的输出结果中我们可以看到从容器中获取到的配置类对象本身就是一个被SpringCGLIB增强了的代理对象
@Configuration()默认设置的是proxyBeanMethods = true。如果@Configuration(proxyBeanMethods = true),就是代理对象调用方法。SpringBoot总会检查这个组件是否在容器中已有,调用配置类中的方法时会返回容器中已有的组件(即IoC容器中已存在的对象)。如果@Configuration(proxyBeanMethods = false),就不是代理对象调用方法,SpringBoot不会检查这个组件是否在容器中已有,调用配置类中的方法时会返回新对象。
@Configuration(proxyBeanMethods = false)举例:
把上述5中的@Configuration()改为@Configuration(proxyBeanMethods = false)
输出结果为:
总结:
Full模式(proxyBeanMethods = true):保证每个@Bean方法被调用多少次返回的组件都是单实例的Lite模式(proxyBeanMethods = false):每个@Bean方法被调用多少次返回的组件都是新创建的组件依赖必须使用Full模式默认。其他默认是否Lite模式配置类组件之间无依赖关系用Lite模式加速容器启动过程,调用配置类中的方法时,SpringBoot每次都不会判断对象在容器中是否已经存在,减少了判断过程配置类组件之间有依赖关系,调用配置类中的方法时,SpringBoot每次都会判断对象在容器中是否已经存在,方法会被调用得到之前单实例组件,用Full模式