@Data
public class Kc {
private String name;
}
@Data
public class User {
private int age;
private Kc kc;
}
/**
*
* 配置类 注册到容器中,默认单实例
* 配置类 本身也是组件
* 相当于以前的bean.xml
* @param
* @return
* @throws Exception
*/
@Configuration
public class TestConfig {
@Bean
public User user1(){
User user=new User();
user.setAge(111);
user.setKc(kc());
return user;
}
@Bean("kc1")
public Kc kc(){
Kc kc=new Kc();
kc.setName("aaa");
return kc;
}
}
@SpringBootApplication
public class ClientApplication {
public static void main(String[] args) {
//返回我们ioc容器
ConfigurableApplicationContext run = SpringApplication.run(ClientApplication.class, args);
//查看容器里面的组件
String[] beanDefinitionNames = run.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
System.out.println("===========================");
//从容器中获取对象
User u1 = run.getBean(User.class);
User u2=run.getBean("user1",User.class);
System.out.println(u1.getClass());
System.out.println(u2.getClass());
System.out.println(u1==u2);
System.out.println("------------------------------");
Kc kc=run.getBean("kc1",Kc.class);
System.out.println(kc.getClass());
System.out.println("------------------------------");
TestConfig testConfig=run.getBean(TestConfig.class);
System.out.println(testConfig);
}
}
当我们使用了@Configuration,那么就会注册到容器中
当使用@Bean("kc1")那么会把容器名字改成kc1
当我们直接使用@Bean,对应的user1()方法名,对应容器里面的名字就是user1
我们的注册到容器的对象,默认是单例模式的,可以看到2个user都一样
并且是cglib动态代理的
默认proxyBeanMethods = true
proxyBeanMethods就是代理bean方法
如果设置为true,springboot启动的时候,都会检查这个组件在容器中是否存在,如果有保持组件单例
并且也是重量级模式(full),bean方法注册的组件都会去容器找组件
proxyBeanMethods = true 并且设置代理bean方法设置为true,组件依赖也是true
就是User里面使用了kc,和KC这个对象一样,所以是组件依赖
proxyBeanMethods = false 当代理bean方法设置为false的时候
TestConfig就不在是代理对象了,而是类本身
springboot在启动的时候,会很快,不会在容器中检查这些方法是否存在
在容器中也不会保存代理对象
并且也解决了组件依赖,就是User里面的kc和Kc类的对象,不一样了
也就是我们的Lite,轻量级模式
使用@Import({User.class}),也可以吧User注册到容器当中
前提必须是配合@Configuration一起使用
把之前的user1方法注释掉
启动类改成下面的代码
public static void main(String[] args) {
long start =System.currentTimeMillis();
//返回我们ioc容器
ConfigurableApplicationContext run = SpringApplication.run(ClientApplication.class, args);
//查看容器里面的组件
String[] beanDefinitionNames = run.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
System.out.println("===========================");
//从容器中获取对象
User u1 = run.getBean(User.class);
System.out.println(u1);
System.out.println("------User对应的容器数组---------");
String[] beanNamesForType = run.getBeanNamesForType(User.class);
for (String s : beanNamesForType) {
System.out.println(s);
}
}
可以看到使用@Import注解,类里面的输入没有赋值,并且在容器里面的名字是类全路径
而我们使用@Bean的注解的时候,都是使用的方法名字在容器中
在来看下@Conditional
条件装配:当满足了某些条件,才会注入到容器中
可以看到有这么多的条件类
我们先把kc1对应的bean注释掉
可以看到kc1不存在容器中
我们在@Bean方法上面加@ConditionalOnBean这个注解name = "kc1"
表示如果没有bean的名字叫kc1的 那么和他有依赖关联的,都不会在容器中注册
可以发现,我已经加了@ConditionalOnBean注解,并且kc1已经注册了
为啥user1还不显示呢?
是顺序问题,把kc1放入user1上面,因为user1的容器注册的时候,kc1还没有注册,所以这里是false
我们把顺序切换后,就打印true了
当我们设置一个不存在容器的kc2,那么打印user1这个容器就是false,不会注册到容器中
我们在看下@ConditionalOnMissingBean(name = "kc1")
如果容器中不存在kc1,那么就会注册到容器中
可以看到,我们的kc1是存在容器中的,所以这里打印的user1就是false,没被注册到容器中
我们在设置kc2不存在容器中,所以都打印true
在springboot中,我们是不使用bean.xml这种方式的
在启动类获取容器的时候发现没有
但是我们可以使用@ImportResource({"classpath:bean.xml"}) 这个注解导入一份资源
把bean.xml导入进来让他注册到容器当中,现在打印就是true了