如何给容器注入组件
首先给出项目的目录结构,其中需要注入的组件是User类和Pet类。
- 方式1:基于原生spring的方式
<bean id="user01" class="com.hpf.boot.bean.User">
<property name="username" value="张三"></property>
<property name="userage" value="25"></property>
</bean>
<bean id="pet01" class="com.hpf.boot.bean.Pet">
<property name="petype" value="汤姆猫"></property>
</bean>
- 方式2:基于SpringBoot框架的方式
import com.hpf.boot.bean.Pet;
import com.hpf.boot.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/*
* 1.配置类里面使用@Bean标注在方法上给容器注册组件,默认是单实例的
* 2.配置类本身也是组件
* 3.boolean proxyBeanMethods() default true;代理bean的方法
* Full模式(全模式):proxyBeanMethods = true
* Lite模式(轻量级模式):proxyBeanMethods = false
* 这个设置主要是为了解决组件依赖问题
* */
@Configuration(proxyBeanMethods = true)//告诉SpringBoot这是一个配置类==配置文件
public class MyConfig {
/*
* 给容器中添加组件。
* 1.以方法名作为组件的id。
* 2.返回类型就是组件类型。
* 3.返回的值就是组件在容器中的实例。*/
/*
* 外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中共的单实例对象*/
@Bean
public User user01(){
User user = new User("张三",25);
return user;
}
@Bean("Tom")//这里可以设置自定义组件的名字
public Pet pet01(){
Pet pet = new Pet("汤姆猫");
return pet;
}
}
在主程序类里面可是测试一下代码:
import com.hpf.boot.bean.Pet;
import com.hpf.boot.bean.User;
import com.hpf.boot.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/*
主程序类
* 告诉编译器这是一个SpringBoot应用*/
@SpringBootApplication(scanBasePackages = "com.hpf")
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);
}*/
//3.从容器中获取组件
Pet tom01= run.getBean("Tom", Pet.class);
Pet tom02= run.getBean("Tom", Pet.class);
//可以证明向容器中注入的组件是单实例的
System.out.println(tom01==tom02);
//说明配置类本身也是一个组件
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);
//如果@Configuration(proxyBeanMethods = true)代理对象调用方法,SpringBoot总会检查这个组件是否在容器里面
//也就是说SpringBoot会保持组件单实例
User user01 = bean.user01();
User user02 = bean.user01();
System.out.println(user01==user02);
}
}
接下来我们用代码的形式测试一下组件依赖具体说的是什么意思?
@Configuration(proxyBeanMethods = true)//告诉SpringBoot这是一个配置类==配置文件
public class MyConfig {
/*
* 给容器中添加组件。
* 1.以方法名作为组件的id。
* 2.返回类型就是组件类型。
* 3.返回的值就是组件在容器中的实例。*/
/*
* 外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中共的单实例对象*/
@Bean
public User user01(){
User user = new User("张三",25);
//User组件依赖了Pet组件(true or false)
user.setPet(pet01());
return user;
}
@Bean("Tom")//这里可以设置自定义组件的名字
public Pet pet01(){
Pet pet = new Pet("汤姆猫");
return pet;
}
}
//以下是主程序的测试代码
MyConfig bean = run.getBean(MyConfig.class);
//获取一个宠物组件
Pet tom01 = run.getBean("Tom", Pet.class);
System.out.println(tom01);
//获取一个用户组件
User user01 = run.getBean("user01",User.class);
System.out.println(user01.getPet());
可以看到当proxyBeanMethods = true时,用户的宠物就是容器里面的宠物。
可以看到当proxyBeanMethods = false时,用户的宠物并不是容器里面的宠物。
总结
- 配置类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断;
- 配置类组件之间有依赖关系,方法会被调用之前单实例组件,用Full模式。