一、BeanFactory与ApplicationContext
一、BeanFactory
-
自定义IOC容器实现:
-
编写Dao,Service代码
-
不需要导入spring 坐标,导入dom4j,jaxen坐标
-
新建常规的xml文件
-
编写BeanFactory
- 读取xml文件流
- dom4j 解析xml文件
- 编写xpath表达式
- 获取xml文件所有bean标签
- 通过反射创建对象实例,存入map
-
public class UsrDefBeanFactory { // 容器 private static Map<String, Object> iocMap = new HashMap<>(); static { try { // 读取xml文件 InputStream inputStream = UsrDefBeanFactory.class.getClassLoader().getResourceAsStream("IUser.xml"); // 解析xml SAXReader saxReader = new SAXReader(); Document document = saxReader.read(inputStream); // xpath表达式 String xpath = "//bean"; // 获取所有bean标签 List<Element> nodes = document.selectNodes(xpath); // 反射建立对象 for (Element node : nodes) { String id = node.attributeValue("id"); String aClass = node.attributeValue("class"); Object o = Class.forName(aClass).newInstance(); iocMap.put(id, o); } } catch (Exception e) { e.printStackTrace(); } } public static Object getBean(String id) { return iocMap.get(id); } }
-
public class IUserServiceImpl implements IUserService { private IUserDao userDao; public void save() { userDao = (IUserDaoImpl) UsrDefBeanFactory.getBean("IUserDao"); userDao.insert(); } }
-
<bean id = "IUserDao" class = "IUserDaoImpl的全限定类名"></bean>
-
-
DefaultListableBeanFactory实现:
-
编写Dao,Service代码
-
导入spring-cotext坐标
-
resources目录下新建Spring Config xml文件(没有导入spring坐标不会显示)
-
编写BeanFactory:
- 使用DefaultListableBeanFactory 工厂
- 创建读取器 XmlBeanDefinitionReader
- 读取器绑定工厂
- 根据id获取bean对象
-
public void testDefaultListableBeanFactory() { // 创建工厂对象 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); // 获取读取器 xml文件 XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); // 读取配置给工厂 reader.loadBeanDefinitions("DUser.xml"); // 根据id获取bean DUserDaoImpl dUserDao = (DUserDaoImpl) beanFactory.getBean("dUserDao"); System.out.println(dUserDao); DUserServiceImpl dUserService = (DUserServiceImpl) beanFactory.getBean("dUserService"); System.out.println(dUserService); }
-
public class DUserServiceImpl implements DUserService { private DUserDao userDao; // BeanFactory 调用该 set 方法,从容器中把 DUserDao 设置到这里 public void setUserDao(DUserDao userDao) { this.userDao = userDao; System.out.println("set user dao running"); } @Override public void save() { userDao.insert(); } }
-
<?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"> <!-- 配置 dao --> <bean id="dUserDao" class="DUserDaoImpl的全限定类名"></bean> <!-- 配置service --> <bean id="dUserService" class="DUserServiceImpl的全限定类名"> <!-- 这里的name 是DUserServiceImpl 里面set方法setUserDao 的UserDao 首字母小写--> <property name="userDao" ref="dUserDao"></property> </bean> </beans>
-
二、ApplicationContext
-
ApplicationContext称为Spring容器,内部封装了BeanFactory,功能比BeanFactory更加强大,使用ApplicationContext是,xml配置文件通常命名为applicationContext.xml
-
public static void main(String[] args) { // 创建ApplicationContext,加载xml文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); // 获取bean UserDaoImpl userDao = (UserDaoImpl) applicationContext.getBean("userDao"); System.out.println(userDao); }
三、BeanFactory与ApplicationContext关系
-
-
Bean初始化时机不同:
- 原始BeanFactory是在调用getBean方法时,才会创建Bean,ApplicationContext是配置文件加载,容器已创建就把Bean实例化好。
- ApplicationContext创建Bean:
- 通过debug可以看到applicationContext对象中有beanFactory对象,beanFactory里面的singletonObjects包含实例化的bean,applicationContext.getBean实际上是调用beanFactory.getBean
- 实例化bean默认调用的是类的无参构造方法
四、BeanFactory集成体系
-
具体的实现类是
DefaultListableBeanFactory
,ApplicationContext中的BeanFactory实现类也是它。 -
-
五、ApplicationContext继承体系
-
-
ClassPathXmlApplicationContext
:加载类路径下的xml配置文件 -
FileSystemXmlApplicationContext
:加载磁盘路径下的xml配置文件
五、ApplicationContext继承体系 -
-
ClassPathXmlApplicationContext
:加载类路径下的xml配置文件 -
FileSystemXmlApplicationContext
:加载磁盘路径下的xml配置文件 -
AnnotationConfigApplicationContext
:加载注解配置类