一、几个问题
- Spring 中的 bean 是如何生成?
- Spring 提供了哪些扩大点能够整合第三方框架
- Spring 如何整合 Mybatis 的
二、什么是 Spring
Spring 治理 bean(Java 中的对象),初始化的操作,
三、Spring IoC 容器
-
资源组件:
Resource,对资源文件的形容,不同资源文件如 xml、properties 文件等,格局不同,最终都将被 ResourceLoader 加载取得相应的 Resource 对象;集体了解是。主配置文件. 主配置作为所有配置的入口
-
资源加载组件:
ResourceLoader:加载 xml、properties 等各类格式文件,解析文件,并生成 Resource 对象。加载哪些解析过的配置资源
-
Bean 容器组件:
BeanFactory 体系:IoC 容器的外围,其余组件都是为它工作的(但不是仅仅为其服务). 外围
-
Bean 注册组件:
SingletonBeanRegister/AliasRegister:将 BeanDefinition 对象注册到 BeanFactory(BeanDefinition Map)中去。注册对象所应用的容器
-
Bean 形容组件:
BeanDefinition 体系,Spring 外部对 Bean 形容的根本数据结构。负责形容 BeanDefinition 资源 将资源模式的 bean 转化为 spring 所冀望的格局构造
-
Bean 结构组件:
BeanDefinitionReader 体系,读取 Resource 并将其数据转换成一个个 BeanDefinition 对象。负责将一个个的资源 解析转化为 BeanDefinition 为之后形容 bean 做筹备
<img src=”https://tva1.sinaimg.cn/large/007S8ZIlgy1gg9jtxriloj31330mi0w2.jpg” alt=”image-20200205095809050″ style=”zoom:50%;float:left” />
四、BeanFactory
4.1 筹备
-
bean-v1.xml
配置bean
的信息 -
BeanDefinition
用于寄存bean
的定义 -
BeanFactory
获取 bean的信息,实例化
bean` -
BeanFactoryTest
测试BeanFactory
是否可用
4.2 代码实现
-
bean-v1.xml
<?xml version="1.0" encoding="UTF-8"?> <beans> <bean id="user" class="com.timwang.spring.small.User"/> <bean id="invalidBean" class="xxx.xxx"/> </beans>
-
BeanDefinition
bean-v1.xml
中定义了每个bean
,但这些信息咱们该如何存储呢?spring
是通过BeanDefinition
接口来形容bean
的定义package com.timwang.spring.small; /** * @author wangjun
*/
public interface BeanDefinition {
/**
* 获取 bean.xml 中 bean 的全名 如 "com.niocoder.service.v1.NioCoderService"
* @return string
*/
String getBeanClassName();
}
`GenericBeanDefinition` 实现了 `BeanDefinition` 接口
package com.timwang.spring.small;
/**
* @author wangjun
* @date 2020-06-29
*/
public class GenericBeanDefinition implements BeanDefinition {
private String id;
private String beanClassName;
public GenericBeanDefinition(String id, String beanClassName) {
this.id = id;
this.beanClassName = beanClassName;
}
@Override
public String getBeanClassName() {return this.beanClassName;}
public String getId() {return id;}
}
3. BeanFactory
咱们曾经应用 `BeanDefinition` 来形容 `bean-v1.xml` 的 `bean` 的定义, 上面咱们应用 `BeanFactory` 来获取 `bean` 的实例
package com.timwang.spring.small;
/**
* 创立 bean 的实例
* @author wangjun
* @date 2020-06-29
*/
public interface BeanFactory {
/**
* 获取 bean 的定义
* @param beanId beanId
* @return BeanDefinition
*/
BeanDefinition getBeanDefinition(String beanId);
/**
* 获取 bean 的实例
* @param beanId beanId
* @return bean 示例
*/
Object getBean(String beanId);
}
`DefaultBeanFactory` 实现了 `BeanFactory` 接口
package com.timwang.spring.small;
import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.util.ClassUtils;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.dom4j.io.SAXReader;
/**
* BeanFactory 的默认实现类
*
* @author wangjun
* @date 2020-06-29
*/
public class DefaultBeanFactory implements BeanFactory {
private static final String ID_ATTRIBUTE = "id";
private static final String CLASS_ATTRIBUTE = "class";
/**
* 寄存 BeanDefinition
*/
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
public DefaultBeanFactory(String configFile) {loadBeanDefinition(configFile);
}
@Override
public BeanDefinition getBeanDefinition(String beanId) {return beanDefinitionMap.get(beanId);
}
@Override
public Object getBean(String beanId) {BeanDefinition bd = this.getBeanDefinition(beanId);
if (bd == null) {throw new BeanCreationException("BeanDefinition does not exist");
}
ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
String beanClassName = bd.getBeanClassName();
try {
// 应用反射创立 bean 的实例,须要对象存在默认的无参构造方法
Class<?> aClass = classLoader.loadClass(beanClassName);
return aClass.newInstance();} catch (Exception e) {throw new BeanCreationException("Bean Definition does not exist");
}
}
/**
* 具体解析 bean.xml 的办法 应用 dom4j
* @param configFile configFile
*/
private void loadBeanDefinition(String configFile) {ClassLoader cl = ClassUtils.getDefaultClassLoader();
try (InputStream is = cl.getResourceAsStream(configFile)) {SAXReader reader = new SAXReader();
Document doc = reader.read(is);
Element root = doc.getRootElement();
Iterator elementIterator = root.elementIterator();
while (elementIterator.hasNext()) {Element ele = (Element) elementIterator.next();
String id = ele.attributeValue(ID_ATTRIBUTE);
String beanClassName = ele.attributeValue(CLASS_ATTRIBUTE);
BeanDefinition bd = new GenericBeanDefinition(id, beanClassName);
this.beanDefinitionMap.put(id, bd);
}
} catch (Exception e) {throw new BeanDefinitionStoreException("IOException parsing XML document", e);
}
}
}
4. BeanFactoryTest
package com.timwang.spring.small;
/**
* @author wangjun
* @date 2020-06-29
*/
public class BeanFactoryTest {
public static void main(String[] args) {BeanFactoryTest beanFactoryTest = new BeanFactoryTest();
beanFactoryTest.testGetBean();}
public void testGetBean() {BeanFactory beanFactory = new DefaultBeanFactory("bean-v1.xml");
BeanDefinition bd = beanFactory.getBeanDefinition("user");
String beanClassName = bd.getBeanClassName();
System.out.println(beanClassName);
}
}