bean实例化三种方式:
- 构造方法(常用)!
- 静态工厂(了解)
- 实例工厂(了解)
- FactoryBean(实用)!
环境准备:
- 创建一个Maven项目
- pom.xml添加Spring依赖
- resources下添加spring的配置文件applicationContext.xml
1.构造方法实例化(常用)
步骤1.准备需要的类BookDao和BookDaoImpl类
package com.hnu.dao.impl;
import com.hnu.dao.BookDao;
//实现接口
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
//运行程序,如果控制台有打印构造函数中的输出,说明Spring容器在创建对象的时候也用的是构造函数
//通过反射的方式获取对象 使用无参构造 无参构造只要当容器被加载就会被执行
//几遍是private修饰也执行,因为Spring默认使用了构造函数创建对象
private BookDaoImpl() {
System.out.println("book dao constructor is running ....");
}
//有参构造 当即有有参构造又有无参构造,运行会报错
/*private BookDaoImpl(int i) {
System.out.println("有参构造 is running ....");
}*/
}
package com.hnu.dao;
//先创建接口,然后创建实现类,最后在App类中引用实现
public interface BookDao {
public void save();
}
步骤2:将类配置到Spring容器
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标签标示配置bean
id属性标示给bean起名字
class属性表示给bean定义类型
-->
<!--name:为bean指定别名,别名可以有多个,使用逗号,分号,空格进行分隔-->
<!--`singleton`默认为单例-->
<bean id="bookDao" name="dao bookDaoImpl" class="com.hnu.dao.impl.BookDaoImpl"/>
步骤3:编写运行程序
package com.hnu;
import com.hnu.dao.BookDao;
import com.hnu.dao.impl.BookDaoImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppForInstanceBook {
public static void main(String[] args) {
//获得容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器中获取对象进行方法调用
BookDao bookDao = (BookDao)ctx.getBean("dao");
//调用方法
bookDao.save();
}
}
运行结果:
如果把前面的有参构造注释取消掉,这时候同时存在有参和无参构造,也不会报错
但是如果把无参构造注释掉。只留下个有参构造,这时候就要报错了,注意一点对于Spring的不报错,我们要从下往上来看,下面的是一些根本性错误(最核心错误),然后依次往上看,
比如:
最后一行:
Caused by: java.lang.NoSuchMethodException: com.hnu.dao.impl.BookDaoImpl.<init>
()
- Caused by 翻译为
引起
,即出现错误的原因 - java.lang.NoSuchMethodException:抛出的异常为
没有这样的方法异常
- com.hnu.dao.impl.BookDaoImpl.
<init>
():哪个类的哪个方法没有被找到导致的异常,<init>
()指定是类的构造方法,即该类的无参构造方法
如果最后一行错误获取不到错误信息,接下来查看第二层:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.hnu.dao.impl.BookDaoImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.hnu.dao.impl.BookDaoImpl.<init>
()
- nested:嵌套的意思,后面的异常内容和最底层的异常是一致的
- Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.hnu.dao.impl.BookDaoImpl]: No default constructor found;
- Caused by:
引发
- BeanInstantiationException:翻译为
bean实例化异常
- No default constructor found:没有一个默认的构造函数被发现
- Caused by:
2.静态工厂实例化
首先准备一下环境,划红线的是上一个构造方法的类,不用管
步骤1:创建OrderDao和OrderDaoImpl类
package com.hnu.dao;
public interface OrderDao {
public void save();
}
package com.hnu.dao.impl;
import com.hnu.dao.OrderDao;
public class OrderDaoImpl implements OrderDao {
public void save() {
System.out.println("order dao save...");
}
}
步骤2:创建一个工厂类OrderDaoFactory并提供一个静态方法
package com.hnu.factory;
import com.hnu.dao.OrderDao;
import com.hnu.dao.impl.OrderDaoImpl;
//静态工厂实例化,返回一个OrderDaoImpl实现对象
public class OrderDaoFactory {
public static OrderDao getOrderDao(){
return new OrderDaoImpl();
}
}
步骤3:将类配置到Spring容器
<?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="orderDao" name="orderDao1" class="com.hnu.factory.OrderDaoFactory" factory-method="getOrderDao"/>
步骤4:创建调用运行的执行类AppForInstanceOrder
package com.hnu;
import com.hnu.dao.OrderDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppForInstanceOrder {
public static void main(String[] args) {
//用spring来管理工厂
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
OrderDao orderDao = (OrderDao) ctx.getBean("orderDao1");
orderDao.save();
}
}
运行结果:
大致步骤为:
先创建接口然后用一个实现类实现接口方法,然后创建一个静态工厂,工厂返回实现类对象,在IOC容器中创建工厂对象,然后在实现类中获取容器并且调用方法
3.实例工厂与FactoryBean
1.实例工厂实例化
环境准备:
步骤1:准备一个UserDao和UserDaoImpl类
package com.hnu.dao;
public interface UserDao {
public void save();
}
package com.hnu.dao.impl;
import com.hnu.dao.UserDao;
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("user dao save ...");
}
}
步骤2:创建一个工厂类UserDaoFactory
package com.hnu.factory;
import com.hnu.dao.UserDao;
import com.hnu.dao.impl.UserDaoImpl;
public class UserDaoFactory {
public UserDao getUserDao() {
//返回一个实现类对象去实现接口中的方法,注意这里不是静态工厂了哦
return new UserDaoImpl();
}
}
步骤3:将类配置到Spring容器
<!--实例化工厂 先获得工厂然后实例化对象-->
<bean id="userDaoFactory" class="com.hnu.factory.UserDaoFactory"/>
<bean id="userDao" factory-bean="userDaoFactory" factory-method="getUserDao"/>
实例化工厂运行的顺序是:
创建实例化工厂对象,对应的是第一行配置
调用对象中的方法来创建bean,对应的是第二行配置
factory-bean:工厂的实例对象
factory-method:工厂对象中的具体创建对象的方法名,对应关系如下:
步骤4:创建调用运行的执行类AppForInstanceUser
package com.hnu;
import com.hnu.dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppForInstanceUser {
public static void main(String[] args) {
//获取容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取bean对象
UserDao userDao = (UserDao) ctx.getBean("userDao");
//执行方法
userDao.save();
}
}
执行结果:
2.FactoryBean使用
简化实例工厂开发
创建一个UserDaoFactoryBean工厂类
package com.hnu.factory;
import com.hnu.dao.UserDao;
import com.hnu.dao.impl.UserDaoImpl;
import org.springframework.beans.factory.FactoryBean;
import javax.jws.soap.SOAPBinding;
//使用接口的形式,实现工厂模式 实例化Bean
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
//替代原来实例工厂中创建对象的方法
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
//返回所创建类的class对象
public Class<?> getObjectType() {
return UserDao.class;
}
//创建的对象是否是单例化
public boolean isSingleton() {
return false;
}
}
将类配置到Spring容器
<?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="userDao" class="com.hnu.factory.UserDaoFactoryBean"/>
运行类和前面实例化工厂一样,这里验证创建的对象是否是单例化
package com.hnu;
import com.hnu.dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppForInstanceUser {
public static void main(String[] args) {
//获取容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取bean对象
UserDao userDao = (UserDao) ctx.getBean("userDao");
UserDao userDao1 = (UserDao) ctx.getBean("userDao");
//执行方法
userDao.save();
System.out.println(userDao);
System.out.println(userDao1);
}
}
运行结果: