Bean实例化的三种方式
Notes
一.使用构造器实例化对象
bean本质就是对象,可以使用构造方法进行实例化
提供一个可访问的构造方法(不写(默认),或者空参)
无参构造器不存在的情况:抛出BeanCreationException
public BookDaoImpl() { |
可以看到bean确实可以使用构造方法实例化,但内部实现过程是通过反射,这里就涉及了后续需要学习的原理
Spring报错如何看?
这里我们使用有参构造模拟报错环境,可以看见非常恐怖
public BookDaoImpl(int i) { |
但是先别慌,Sping异常从下向上找,Caused by开始
没有无参构造方法(这里的核心原因,有可能是spring内部异常,所以需要往上找)NoSuchMethodException: com.mvnweb.dao.impl.BookDaoImpl.
() 没有默认的构造方法被发现(原因是我们写了无参构造,不送参数,导致默认占用)BeanInstantiationException: Failed to instantiate [com.mvnweb.dao.impl.BookDaoImpl]: No default constructor found
Bean实例化失败,原因是没有默认构造 (可以看出上一条原因,也被带到了这里的报错信息)BeanCreationException: Error creating bean with name ‘bookDao’ defined in class path resource [applicationContext.xml]: Failed to instantiate [com.mvnweb.dao.impl.BookDaoImpl]: No default constructor found
总结:spring的报错都是从下向上逐渐积压的,大部分时候从下第一个都能解决问题,除非遇到spring内部问题,所以需要向上找
二.使用静态工厂(了解)
早些年使用工厂来造对象,以进行一定的解耦,这里是简单工厂的一个例子
//OrderDao.class |
bean相应配置:这里真正造对象的是工厂方法getOrderDao
# class决定了这里是factory的对象,所以实例化需要使用factory-method |
配置完后使用容器实例化orderDao对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); |
三.使用实例工厂(了解)
与静态工厂不同,实例化方法不带static,获取对象时就不能直接OrderDaoFactory.getOrderDao()
//使用实例工厂获得对象 userDaoFactory.getUserDao(); |
既然是实例工厂,接下来先造工厂factory Bean对象,实例bean对象通过factory Bean提供方法来实例化bean
<bean id="userDaoFactory" class="com.mvnweb.factory.UserDaoFactory"/> |
接下来还是一样使用Ioc容器对象来获取Bean
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); |
现在会发现,这里的工厂Bean只是配合使用来造Bean对象,本身没有实际意义,而且方法不固定的话,每一次都需要配置。
于是Spring针对这种模式进行改良:
不造无用工厂bean,固定实例化方法
四.使用FactoryBean实例化(务必掌握)
既然是Spring提供,那么自然想到他的实现标准,以及对应提供的接口:FactoryBean<?>
//实现FactoryBean接口 |
这样做的好处是什么呢? → 简化配置
可以看到,相比于前两种工厂,这里的配置十分简洁
<bean id="userDao" class="com.mvnweb.factory.UserDaoFactory"/> |
在最后学习框架整合的时候,大部分框架都使用这种方式与spring打交道