1. bean的管理,比较重要的知识点
bean默认使用单例模式进行对象的管理,因此不仅IoC是单例的,IoC里面的对象也是单例的。可以使用 scope关键字控制管理的对象是单例(singleton)还是多例(prototype)。
2. bean 的实例化方式
方式一:构造方法实例化bean
通过构造方法构造对象是使用反射的方式,调用的是该对象的无参构造方法,把该对象的无参构造方法改成 private也可以通过反射调用,但是如果重写一个有参构造方式,那么bean在构造对象的时候就找不到相应的方法,便会报错。因此让bean托管的对象一定得保证有无参构造器。
<bean id="bookDao" class="com.dao.impl.BookDaoImpl"/>
方式二:使用静态工厂实例化bean
需要在配置中把 class设置为工厂类,把 factory-method设置为工厂函数:
<bean id="orderDao" class="com.factory.OrderDaoFactory" factory-method="getOrderDao"/>
方式三:使用实例工厂实例化bean
<bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/>
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
方式四:使用FactoryBean实例化bean
<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>
相当于对方式三做了个简化,使用非静态函数 getObject()默认为 factory-method。
需要注意的是 UserDaoFactoryBean 作为工厂类,需要继承 FactoryBean<T>接口,接口三个函数:
T getObject() throws Exception;
Class<?> getObjectType();
public boolean isSingleton() {
return true;
}
其中 isSingleton()方法可以设置实例化的对象是否为单例,但是在配置中通过 scope 也能设置对象是否为单例,当两个都配置了的话,只有两个地方都配置了单例,才会是单例。
isSingleton和scope不同组合条件下,bean的类型
3. bean的生命周期
创建bean的初始化和销毁时执行的函数:
方法一、通过 init-method和 destroy-method标签。
<bean id="bookDao" class="com.study.spring.Dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy" />
方法二、通过继承接口实现,不用带标签了
public class BookDaoImpl implements BookDao, InitializingBean, DisposableBean {
@Override
public void save(String data) {
System.out.println("Save " + data + " success!\n");
}
// 销毁时的操作
@Override
public void destroy() {
System.out.println("service destroy...");
}
// 初始化时候的操作
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("service init...");
}
}
假如两种方式同时设置,则两种方法都会分别调用。
对于bean的生命周期控制在bean的整个生命周期中所处的位置如下:
初始化容器:
-
1.创建对象(内存分配)
-
2.执行构造方法
-
3.执行属性注入(set操作)
-
4.执行bean初始化方法
使用bean :
-
1.执行业务操作 关闭/销毁容器
-
2.执行bean销毁方法
4. 依赖注入
方法一、通过构造器注入,使用 constructor-arg标签,类中提供构造器
基本数据类型用name指定构造器形参,基本数据类型用 value指定值,对象用 ref指定 bean id。
<bean id="bookDao" class="com.study.spring.Dao.impl.BookDaoImpl" >
<constructor-arg name="connectNum" value="11"></constructor-arg>
<constructor-arg name="mysqlName" value="mysql-5.0"></constructor-arg>
</bean>
<bean id="userDao" class="com.study.spring.Dao.impl.UserDaoImpl" />
<bean id="bookService" class="com.study.spring.service.impl.BookServiceImpl">
<constructor-arg name="bookDao" ref="bookDao"></constructor-arg>
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
name属性对应的值为构造函数中方法形参的参数名,必须要保持一致。 ref属性指向的是spring的IOC容器中其他bean对象。
通过 index或 type 设置参数在构造函数中的位置或者类型,进行对应。
<constructor-arg type="int" value="11"></constructor-arg>
<constructor-arg type="String" value="mysql-5.0"></constructor-arg>
<constructor-arg index="0" value="11"></constructor-arg>
<constructor-arg index="1" value="mysql-5.0"></constructor-arg>
方法二、通过setter注入,需要类提供setter方法
变量名用name指定,基本数据类型用value指定值,对象用ref标签指定bean id
<bean ...>
< property name="" value=""/>
< property name="" ref=""/>
</bean>
依赖注入方式的选择
-
强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现 强制依赖指对象在创建的过程中必须要注入指定的参数
-
可选依赖使用setter注入进行,灵活性强 可选依赖指对象在创建过程中注入的参数可有可无
-
Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相 对严谨
-
如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选 依赖的注入
-
实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注 入
-
自己开发的模块推荐使用setter注入
5.依赖自动装配
-
按类型(常用)
-
按名称
-
按构造方法
-
不启用自动装配