Spring官方文档: Bean 实例化
一、通过构造函数实例化

验证是否是通过构造函数实例化
在 BookDaoImpl
中创建构造函数,并在构造函数中输出一段话。
1 2 3 4 5 6 7 8 9 10 11
| public class BookDaoImpl implements BookDao {
public BookDaoImpl(){ System.out.println("book dao constructor is Running..."); }
@Override public void save() { System.out.println("book dao save !!!"); } }
|
控制台输出
可以看到,在控制台已经输出了这段话
App 启动类调用为:5. bean 基础配置 中的实现代码

问题:
- 如果将构造函数改为
private
,Spring 还能进行实例化吗?
- 可以,因为 Spring 是通过 反射 获取的对象实例
- 如果将构造函数改为有参构造函数,Spring 还能进行实例化吗?
- 如果没有无参构造的话,此时会抛出异常,如果有无参构造则还可以正常实例化。
记录一个异常

如果出现了 NoSuchMethodException
,则说明 Spring 没有找到某个方法 cn.pangcy.dao.impl.BookDaoImpl.<init>() 则说明了没有在 BookDaoImpl
中找到 init 即无参构造方法。
记录一个阅读 Spring 报错信息的技巧
阅读 Spring 报错信息要从最后一行往上看,因为 Spring 会从下将每一行错误信息携带道尾部输出当前行错误
如上图异常中,最后一行 NoSuchMethodException
, 在倒数第二行 BeanInstantiationException
尾部出现,而 BeanInstantiationException
中错误信息会被追加到第一个错误信息的尾部出现。
二、使用静态工厂实例化

静态工厂
factory/BookDaoFactory
1 2 3 4 5 6
| public class BookDaoFactory { public static BookDao getBookDao(){ System.out.println("factory setup ...."); return new BookDaoImpl(); } }
|
配置
applicationContext.xml
- 改变一: class 从原本指向
cn.pangcy.dao.impl.BookDaoImpl
改为 cn.pangcy.factory.BookDaoFactory
- 改变二: bean 上添加
factory-method
指定运行的静态工厂函数
如果不指定 factory-method
,那么实例化出来的是这个工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bookDao" name="dao" class="cn.pangcy.factory.BookDaoFactory" factory-method="getBookDao"/>
<bean id="bookService" name="service bookService2 bookEbi" class="cn.pangcy.service.impl.BookServiceImpl" scope="prototype"> <property name="bookDao" ref="dao"/> </bean> </beans>
|
三、实例工厂初始化对象

实例工厂
factory/OrderDaoFactory
和静态工厂的区别是,他不是一个静态方法
1 2 3 4 5
| public class OrderDaoFactory { public OrderDao getOrderDao(){ return new OrderDaoImpl(); } }
|
配置
applicationContext.xml
- 改变一:需要新增一个 bean 作为这个工厂的 bean :
orderDaoFactory
- 改变二:Dao bean 中,不需要指定
class
了,改为指定 factory-bean
- 改变二:Dao bean 中,依旧需要像静态工厂一样指定
factory-mehod
1 2 3 4 5 6 7 8 9 10 11 12
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="orderDaoFactory" class="cn.pangcy.factory.OrderDaoFactory"/> <bean id="orderDao" name="dao" factory-bean="orderDaoFactory" factory-method="getOrderDao"/>
<bean id="orderService" class="cn.pangcy.service.impl.OrderServiceImpl" scope="prototype"> <property name="orderDao" ref="orderDao"/> </bean> </beans>
|
四、使用 FactoryBean 初始化对象

实现 FactoryBean
通过实现 FactoryBean, 实例化 Bean
FactoryBean 主要需要重写 getObject
和 getObjectType
两个方法,getObject
代替原始实例工厂中创建对象的方法,getObjectType
返回对象的类型
isSingleton
设置是否单例的默认值,如果在 bean 中配置了 scoped
则以 bean 中配置为准
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class OrderDaoFactoryBean implements FactoryBean<OrderDao> {
@Override public OrderDao getObject() throws Exception { return new OrderDaoImpl(); }
@Override public Class<?> getObjectType() { return OrderDao.class; }
@Override public boolean isSingleton() { return false; } }
|
配置
applicationContext.xml
配置方式和常规构造方法配置一致。
1 2 3 4 5 6 7 8 9 10 11
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="orderDaoFactory" name="dao" class="cn.pangcy.factory.OrderDaoFactoryBean"/> <bean id="orderService" class="cn.pangcy.service.impl.OrderServiceImpl" > <property name="orderDao" ref="dao"/> </bean> </beans>
|