bean 实例化

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">
<!--
class 中指定为 BookDao 的工厂类
添加属性 factory-method 指定运行那个工厂函数
-->
<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 主要需要重写 getObjectgetObjectType 两个方法,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;
}

// 是否是单例模式
// 这里是设置默认值,如果 bean 中配置了 scoped 以,bean 中配置为准
@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">

<!-- 使用 FactoryBean 实例话 Bean -->
<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>

bean 实例化
https://blog.pangcy.cn/2023/04/02/后端编程相关/java/spring/bean 实例化/
作者
子洋
发布于
2023年4月2日
许可协议