01-Spring容器基本使用及原理
IOC容器
负责对象的实例化,对象的初始化,对象和对象之间依赖关系配置,对象的销毁,对外提供对象的查找,对象的整个生命周期都是由容器来控制的。当我们需要使用的时候直接从ioc容器中直接获取就可以了。
spring ioc容器时如何知道需要管理哪些对象的?
需要我们给ioc容器提供一个配置清单,这个配置支持xml格式和java注解的方式,当spring容器启动时,就会加载这个配置文件,然后将这些对象给组装好以供外部访问者使用。这里所说的ioc容器也叫spring容器
Bean概念
有spring容器管理的对象统称为Bean对象
spring容器使用步骤
- 引入spring相关的maven配置
- 创建bean配置文件,比如bean xml配置文件
- 在bean xml文件中定义好需要spring容器管理的bean对象
- 创建spring容器,并给容器指定需要装载的bean配置文件,当spring容器启动之后,会加载这些配置文件,然后创建好配置文件中定义好的bean对象,将这些对象放在容器中以供使用
- 通过容器提供的方法获取容器中的对象,然后使用
spring容器对象
spring内部提供了很多表示spring容器的接口和对象,我们来看看比较常见的几个容器接口和具体实现类
Bean Factory接口
spring容器的顶层接口,提供了最基本的功能
常见的几个方法
//按bean的id或者别名查找容器中的bean
Object getBean(String name) throws BeansException
//这个是一个泛型方法,按照bean的id或者别名查找指定类型的bean,返回指定类型的bean对象
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
//返回容器中指定类型的bean对象
<T> T getBean(Class<T> requiredType) throws BeansException;
//获取指定类型bean对象的获取器,这个方法比较特别,以后会专门来讲
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
ApplicationContext接口
继承了Bean Factory接口,内部包含了Bean Factory所有的功能,并且在其上进行了扩展,增加了很多企业级功能:aop,国际化,事件支持等等。
ClassPathXmlApplicationContext类
实现了ApplicationContext接口,可以看出这个类容器可以从class path中加载bean.xml配置文件,然后创建xml中配置的bean对象
AnnotationConfigApplicationContext类
同样实现了ApplicationContext接口,当我们使用的方式定义bean的时候,就需要用到这个容器来装载,这个容器内部会解析注解来构建和管理需要的bean
创建bean实例这些方法
通过反射调用构造方法创建对象
调用类的构造方法获取对应的bean实例,是使用最多的方式,这种方式只需要在xml bean元素中指定class属性,spring容器内部会自动调用该类型的构造方法来创建bean对象,将其放在容器中以供使用。
通过静态代码工厂创建bean
我们可以创建静态工厂,内部提供一些静态方法来生成所需要的对象,将这些静态方法创建的对象交由spring以供使用
<bean id="bean名称" name="" class="静态工厂完整类名" factory-method="静态工厂的方法">
<constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
<constructor-arg index="1" value="bean的值" ref="引用的bean名称" />
<constructor-arg index="2" value="bean的值" ref="引用的bean名称" />
....
<constructor-arg index="n" value="bean的值" ref="引用的bean名称" />
</bean>
自定义一个静态工厂
public class UserStaticFactory {
/**
* 静态无参方法创建UserModel
*
* @return
*/
public static UserModel buildUser1() {
System.out.println(UserStaticFactory.class + ".buildUser1()");
UserModel userModel = new UserModel();
userModel.setName("我是无参静态构造方法创建的!");
return userModel;
}
/**
* 静态有参方法创建UserModel
*
* @param name 名称
* @param age 年龄
* @return
*/
public static UserModel buildUser2(String name, int age) {
System.out.println(UserStaticFactory.class + ".buildUser2()");
UserModel userModel = new UserModel();
userModel.setName(name);
userModel.setAge(age);
return userModel;
}
bean.xml配置
<!-- 通过工厂静态无参方法创建bean对象 -->
<bean id="createBeanByStaticFactoryMethod1" class="com.javacode2018.lesson001.demo3.UserStaticFactory"
factory-method="buildUser1"/>
<!-- 通过工厂静态有参方法创建bean对象 -->
<bean id="createBeanByStaticFactoryMethod2" class="com.javacode2018.lesson001.demo3.UserStaticFactory"
factory-method="buildUser2">
<constructor-arg index="0" value="通过工厂静态有参方法创建UerModel实例对象"/>
<constructor-arg index="1" value="30"/>
</bean>
通过实例工厂方法创建bean对象
让spring容器去调用某些对象的某些实例方法来生成bean对象放在容器中以供使用。
<bean id="bean名称" factory-bean="需要调用的实例对象bean名称" factory-method="bean对象中的方法">
<constructor-arg index="0" value="bean的值" ref="引用的bean名称" />
<constructor-arg index="1" value="bean的值" ref="引用的bean名称" />
<constructor-arg index="2" value="bean的值" ref="引用的bean名称" />
....
<constructor-arg index="n" value="bean的值" ref="引用的bean名称" />
</bean>
spring容器以factory-bean的值为bean名称查找对应的bean对象,然后调用该对象中factory-method属性值指定的方法,将这个方法返回的对象作为当前bean对象放在容器中供使用。
自定义一个实例工厂
public class UserFactory {
public UserModel buildUser1() {
System.out.println("----------------------1");
UserModel userModel = new UserModel();
userModel.setName("bean实例方法创建的对象!");
return userModel;
}
public UserModel buildUser2(String name, int age) {
System.out.println("----------------------2");
UserModel userModel = new UserModel();
userModel.setName(name);
userModel.setAge(age);
return userModel;
}
}
bean.xml
<!-- 定义一个工厂实例 要先将实例工厂对象添加到spring容器中-->
<bean id="userFactory" class="com.javacode2018.lesson001.demo3.UserFactory"/>
<!-- 通过userFactory实例的无参user方法创建UserModel对象 -->
<bean id="createBeanByBeanMethod1" factory-bean="userFactory" factory-method="buildUser1"/>
<!-- 通过userFactory实例的有参user方法创建UserModel对象 -->
<bean id="createBeanByBeanMethod2" factory-bean="userFactory" factory-method="buildUser2">
<constructor-arg index="0" value="通过bean实例有参方法创建UserModel实例对象"/>
<constructor-arg index="1" value="30"/>
</bean>
通过FactoryBean来创建bean对象
BeanFactory是spring容器的顶层接口,而这里要说的是FactoryBean,也是一个接口,FactoryBean可以让spring容器通过这个接口的实现来创建我们需要的bean对象
FactoryBean接口源码:
public interface FactoryBean<T> {
/**
* 返回创建好的对象
*/
@Nullable
T getObject() throws Exception;
/**
* 返回需要创建的对象的类型
*/
@Nullable
Class<?> getObjectType();
/**
* bean是否是单例的
**/
default boolean isSingleton() {
return true;
}
}
接口中有3个方法,前面2个方法需要我们去实现,getObject方法内部由开发者自己去实现对象的创建,然后将创建好的对象返回给Spring容器,getObjectType需要指定我们创建的bean的类型;最后一个方法isSingleton表示通过这个接口创建的对象是否是单例的,如果返回false,那么每次从容器中获取对象的时候都会调用这个接口的getObject() 去生成bean对象。
案例
创建一个FactoryBean实现类
public class UserFactoryBean implements FactoryBean<UserModel> {
int count = 1;
@Nullable
@Override
public UserModel getObject() throws Exception { //@1
UserModel userModel = new UserModel();
userModel.setName("我是通过FactoryBean创建的第"+count+++ "对象");//@4
return userModel;
}
@Nullable
@Override
public Class<?> getObjectType() {
return UserModel.class; //@2
}
@Override
public boolean isSingleton() {
return true; //@3
}
}