本篇博客参考github开源项目https://github.com/code4craft/tiny-spring,从零开始手写简易版Spring框架,并且给予更详细的注释和个人见解。
1.构建BeanFactory,创建bean的实例
/**
* @author Jalen.Deng
* @description bean工厂-最基本的容器
* @date 2020/11/23 20:36
**/
public class BeanFactory {
//创建beanDefinitionMap来存储bean的实例
private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
public Object getBean(String name) {
return beanDefinitionMap.get(name).getBean();
}
/**
* 注册bean到beanDefinitionMap中
* @param name
* @param beanDefinition
*/
public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
beanDefinitionMap.put(name, beanDefinition);
}
}
/**
* @author Jalen.Deng
* @description bean定义,可以理解为层层包装后的bean
* @date 2020/11/23 20:46
**/
public class BeanDefinition {
private Object bean;
public BeanDefinition(Object bean) {
this.bean = bean;
}
public Object getBean() {
return bean;
}
}
/**
* @author Jalen.Deng
* @description
* @date 2020/11/23 20:51
**/
public class BeanFactoryTest {
public static void main(String[] args) {
//初始化beanFactory
BeanFactory beanFactory = new BeanFactory();
//创建bean实例
BeanDefinition helloWorldServiceBean = new BeanDefinition(new HelloWorldService());
//注册bean实例到beanFactory
beanFactory.registerBeanDefinition("helloWorldService",helloWorldServiceBean);
//通过getBean()方法获取bean实例
HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService");
//调用hello方法
helloWorldService.helloWorld();
}
}
对比Spring中的实现 DefaultListableBeanFactory 中 registerBeanDefinition 和getBean方法
@SuppressWarnings("unchecked")
@Override
public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
if (resolved == null) {
throw new NoSuchBeanDefinitionException(requiredType);
}
return (T) resolved;
}
/**
* NoSuchBeanDefinitionException是一个很常见的报错,缺少bean的定义,简单来说,就是
* Spring在启动的时候会去实例化所有bean对象,结果没有在context上找到该实例。如果你使用注解,
* 那么就是impl没有用@Service进行注册,如果你使用xml配置,就是没有使用<bean />进行配置
*/
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
//篇幅有限,删减一些校验判断代码
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
//这个配置很关键,允许bean定义覆盖,一般报BeanDefinitionOverrideException
//就是没有开启这个配置
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
//核心就是这段代码
this.beanDefinitionMap.put(beanName, beanDefinition);
}
}
2.构建AbstractBeanFactory,将bean加入工厂进行管理。
package com.dl.spring.factory;
import com.dl.spring.BeanDefinition;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Jalen.Deng
* @description 定义BeanFactory工厂接口
* @date 2020/11/23 20:36
**/
public interface BeanFactory {
/**
* 通过beanName获取bean实例
* @param name
* @return
*/
Object getBean(String name);
/**
* 注册bean到beanDefinitionMap中
* @param name
* @param beanDefinition
*/
void registerBeanDefinition(String name, BeanDefinition beanDefinition);
}
package com.dl.spring;
/**
* @author Jalen.Deng
* @description bean定义,可以理解为层层包装后的bean。
* @date 2020/11/23 20:46
**/
public class BeanDefinition {
private Object bean;
private Class beanClass;
private String beanClassName;
public BeanDefinition() {
}
public void setBean(Object bean) {
this.bean = bean;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
public String getBeanClassName() {
return beanClassName;
}
public void setBeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
try {
this.beanClass = Class.forName(beanClassName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public Object getBean() {
return bean;
}
}
/**
* @author Jalen.Deng
* @description 抽象bean工厂
* @date 2020/11/23 21:31
**/
public abstract class AbstractBeanFactory implements BeanFactory {
/**
*创建beanDefinitionMap来存储bean的实例
*/
private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
@Override
public Object getBean(String name) {
return beanDefinitionMap.get(name).getBean();
}
/**
* 注册bean到beanDefinitionMap中
* @param name
* @param beanDefinition
*/
@Override
public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
Object bean = doCreateBean(beanDefinition);
beanDefinition.setBean(bean);
beanDefinitionMap.put(name, beanDefinition);
}
/**
* 初始化bean
* @param beanDefinition
* @return
*/
protected abstract Object doCreateBean(BeanDefinition beanDefinition);
}
package com.dl.spring.factory;
import com.dl.spring.BeanDefinition;
/**
* @author Jalen.Deng
* @description 自动装配,通过反射创建bean对象
* @date 2020/11/23 21:35
**/
public class AutowireCapableBeanFactory extends AbstractBeanFactory {
@Override
protected Object doCreateBean(BeanDefinition beanDefinition) {
Object bean = null;
try {
bean = beanDefinition.getBeanClass().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return bean;
}
}
对比Spring实现:AbstractAutowireCapableBeanFactory#createBean#doCreateBean。可以自己debug跟踪
3.为bean注入属性(重要)
public abstract class AbstractBeanFactory implements BeanFactory {
/**
*创建beanDefinitionMap来存储bean的实例
*/
private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
@Override
public Object getBean(String name) {
return beanDefinitionMap.get(name).getBean();
}
/**
* 注册bean到beanDefinitionMap中
* @param name
* @param beanDefinition
*/
@Override
public void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception {
Object bean = doCreateBean(beanDefinition);
beanDefinition.setBean(bean);
beanDefinitionMap.put(name, beanDefinition);
}
/**
* 初始化bean
* @param beanDefinition
* @return
*/
protected abstract Object doCreateBean(BeanDefinition beanDefinition) throws Exception;
}
/**
* @author Jalen.Deng
* @description 自动装配工厂,通过反射new对象
* @date 2020/11/23 21:35
**/
public class AutowireCapableBeanFactory extends AbstractBeanFactory {
@Override
protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception {
Object bean = createBeanInstance(beanDefinition);
applyPropertyValues(bean, beanDefinition);
return bean;
}
protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Exception {
for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) {
Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());
declaredField.setAccessible(true);
declaredField.set(bean, propertyValue.getValue());
}
}
protected Object createBeanInstance(BeanDefinition beanDefinition) throws Exception {
return beanDefinition.getBeanClass().newInstance();
}
}
/**
* @author Jalen.Deng
* @description bean的内容及元数据,保存在BeanFactory中,包装bean的实体
* @date 2020/11/23 20:46
**/
public class BeanDefinition {
private Object bean;
private Class beanClass;
private String beanClassName;
private PropertyValues propertyValues;
public BeanDefinition() {
}
public void setBean(Object bean) {
this.bean = bean;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
public String getBeanClassName() {
return beanClassName;
}
public void setBeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
try {
this.beanClass = Class.forName(beanClassName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public Object getBean() {
return bean;
}
public PropertyValues getPropertyValues() {
return propertyValues;
}
public void setPropertyValues(PropertyValues propertyValues) {
this.propertyValues = propertyValues;
}
}
/**
* @author Jalen.Deng
* @description 为bean注入属性
* @date 2020/11/24 9:09
**/
public class PropertyValue {
private final String name;
private final Object value;
public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public Object getValue() {
return value;
}
}
/**
* @author Jalen.Deng
* @description 包装一个对象所有的PropertyValue。
* 为什么封装而不是直接用List?因为可以封装一些操作。
* @date 2020/11/24 9:08
**/
public class PropertyValues {
private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>();
public PropertyValues() {
}
public void addPropertyValue(PropertyValue pv) {
//TODO:这里可以对于重复propertyName进行判断,直接用list没法做到
this.propertyValueList.add(pv);
}
public List<PropertyValue> getPropertyValues() {
return this.propertyValueList;
}
}
/**
* @author Jalen.Deng
* @description
* @date 2020/11/23 21:50
**/
public class BeanFactoryTest {
public static void main(String[] args) throws Exception {
//初始化bean工厂
BeanFactory beanFactory = new AutowireCapableBeanFactory();
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanClassName("com.dl.spring.HelloWorldService");
PropertyValues propertyValues = new PropertyValues();
//为bean注入属性,name属性在HelloWorldService定义好
propertyValues.addPropertyValue(new PropertyValue("name","jalen"));
beanDefinition.setPropertyValues(propertyValues);
//生成bean
beanFactory.registerBeanDefinition("helloWorldService", beanDefinition);
//获取bean
HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService");
helloWorldService.helloWorld();
}
}
对比Spring实现:AbstractAutowireCapableBeanFactory#createBean#doCreateBean#populateBean#applyPropertyValues。可以自己debug跟踪
populateBean.java
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//通过名称或者类型去注入属性
以上就是Spring的核心代码,底层使用的是反射机制。初始化bean要写这么多代码实在是费劲,我们来优化一下。
4.读取xml配置来初始化bean
package com.dl.spring.io;
import java.io.IOException;
import java.io.InputStream;
/**
* @author Jalen.Deng
* @description Resource是spring内部定位资源的接口。
* @date 2020/11/24 14:34
**/
public interface Resource {
InputStream getInputStream() throws IOException;
}
package com.dl.spring.io;
import java.net.URL;
/**
* @author Jalen.Deng
* @description 资源加载器
* @date 2020/11/24 14:35
**/
public class ResourceLoader {
public Resource getResource(String location){
URL resource = this.getClass().getClassLoader().getResource(location);
return new UrlResource(resource);
}
}
package com.dl.spring.io;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
/**
* @author Jalen.Deng
* @description url资源类
* @date 2020/11/24 14:35
**/
public class UrlResource implements Resource {
private final URL url;
public UrlResource(URL url) {
this.url = url;
}
@Override
public InputStream getInputStream() throws IOException {
URLConnection urlConnection = url.openConnection();
urlConnection.connect();
return urlConnection.getInputStream();
}
}
核心类xmlBeanDefinitionReader
package com.dl.spring.xml;
import com.dl.spring.AbstractBeanDefinitionReader;
import com.dl.spring.BeanDefinition;
import com.dl.spring.PropertyValue;
import com.dl.spring.io.Resource;
import com.dl.spring.io.ResourceLoader;
import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
/**
* @author Jalen.Deng
* @description xml解析bean定义
* @date 2020/11/24 14:32
**/
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
public XmlBeanDefinitionReader(ResourceLoader resourceLoader) {
super(resourceLoader);
}
@Override
public void loadBeanDefinitions(String location) throws Exception {
//使用io输入流获取xml中所有bean信息
InputStream inputStream = getResourceLoader().getResource(location).getInputStream();
//加载解析xml
doLoadBeanDefinitions(inputStream);
}
/**
* @param inputStream
* @throws Exception
*/
protected void doLoadBeanDefinitions(InputStream inputStream) throws Exception {
//学过xml相关知识我们可以知道,要获取xml内容首先要构建dom树对象
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
//Document是个接口,代表整个html或者xml文档,是文档树的根
Document doc = documentBuilder.parse(inputStream);
registerBeanDefinitions(doc);
inputStream.close();
}
protected void registerBeanDefinitions(Document doc) {
//getDocumentElement允许直接访问文档元素的子节点
Element root = doc.getDocumentElement();
//解析bean定义核心方法
parseBeanDefinitions(root);
}
protected void parseBeanDefinitions(Element root) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
processBeanDefinition(ele);
}
}
}
protected void processBeanDefinition(Element ele) {
/**
*<bean name="helloWorldService" class="com.dl.spring.HelloWorldService">
* <property name="name" value="Hello World!"></property>
* </bean>
*/
String name = ele.getAttribute("name");
String className = ele.getAttribute("class");
BeanDefinition beanDefinition = new BeanDefinition();
processProperty(ele,beanDefinition);
beanDefinition.setBeanClassName(className);
getRegistry().put(name, beanDefinition);
}
private void processProperty(Element ele, BeanDefinition beanDefinition) {
//其实就是解析 <property name="name" value="Hello World!"></property>
NodeList propertyNode = ele.getElementsByTagName("property");
for (int i = 0; i < propertyNode.getLength(); i++) {
Node node = propertyNode.item(i);
if (node instanceof Element) {
Element propertyEle = (Element) node;
String name = propertyEle.getAttribute("name");
String value = propertyEle.getAttribute("value");
beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name,value));
}
}
}
}
package com.dl.spring;
import com.dl.spring.io.ResourceLoader;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Jalen.Deng
* @description
* @date 2020/11/24 14:43
**/
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader{
//存储bean定义信息的map
private Map<String,BeanDefinition> registry;
private ResourceLoader resourceLoader;
public AbstractBeanDefinitionReader(ResourceLoader resourceLoader) {
this.registry = new ConcurrentHashMap<String, BeanDefinition>();
this.resourceLoader = resourceLoader;
}
public Map<String, BeanDefinition> getRegistry() {
return registry;
}
public ResourceLoader getResourceLoader() {
return resourceLoader;
}
}
package com.dl.spring;
/**
* @author Jalen.Deng
* @description bean的内容及元数据,保存在BeanFactory中,包装bean的实体
* @date 2020/11/23 20:46
**/
public class BeanDefinition {
private Object bean;
private Class beanClass;
private String beanClassName;
private PropertyValues propertyValues = new PropertyValues();;
public BeanDefinition() {
}
public void setBean(Object bean) {
this.bean = bean;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
public String getBeanClassName() {
return beanClassName;
}
public void setBeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
try {
this.beanClass = Class.forName(beanClassName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public Object getBean() {
return bean;
}
public PropertyValues getPropertyValues() {
return propertyValues;
}
public void setPropertyValues(PropertyValues propertyValues) {
this.propertyValues = propertyValues;
}
}
package com.dl.spring;
/**
* @author Jalen.Deng
* @description 从配置中读取BeanDefinitionReader
* @date 2020/11/24 14:43
**/
public interface BeanDefinitionReader {
void loadBeanDefinitions(String location) throws Exception;
}
其他类与前面步骤保持不变,最后测试
package com.dl.spring.xml;
import com.dl.spring.BeanDefinition;
import com.dl.spring.io.ResourceLoader;
import org.junit.Test;
import java.util.Map;
/**
* @author Jalen.Deng
* @description 测试读取配置文件
* @date 2020/11/24 14:42
**/
public class XmlBeanDefinitionReaderTest {
public static void main(String[] args) throws Exception{
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
Map<String, BeanDefinition> registry = xmlBeanDefinitionReader.getRegistry();
System.out.println(registry.get("helloWorldService"));
}
@Test
public void test() throws Exception{
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
Map<String, BeanDefinition> registry = xmlBeanDefinitionReader.getRegistry();
System.out.println(registry.get("helloWorldService"));
}
}
package com.dl.spring;
import com.dl.spring.factory.AutowireCapableBeanFactory;
import com.dl.spring.factory.BeanFactory;
import com.dl.spring.io.ResourceLoader;
import com.dl.spring.xml.XmlBeanDefinitionReader;
import java.util.Map;
/**
* @author Jalen.Deng
* @description
* @date 2020/11/23 21:50
**/
public class BeanFactoryTest {
public static void main(String[] args) throws Exception {
// 1.读取配置
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
// 2.初始化BeanFactory并注册bean
BeanFactory beanFactory = new AutowireCapableBeanFactory();
for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) {
beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());
}
// 3.获取bean
HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService");
helloWorldService.helloWorld();
}
}
package com.dl.spring.io;
import org.junit.Assert;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
/**
* @author Jalen.Deng
* @description 使用resource读取配置文件
* @date 2020/11/24 14:42
**/
public class ResourceLoaderTest {
@Test
public void test() throws IOException {
ResourceLoader resourceLoader = new ResourceLoader();
Resource resource = resourceLoader.getResource("spring.xml");
InputStream inputStream = resource.getInputStream();
Assert.assertNotNull(inputStream);
}
}
resources文件夹下添加spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean name="helloWorldService" class="com.dl.spring.HelloWorldService">
<property name="name" value="Hello World!"></property>
</bean>
</beans>
loadBeanDefinitions的流程图
对应Spring实现:XmlBeanDefinitionReader#loadBeanDefinitions#doLoadBeanDefinitions
流程很复杂,因此不贴代码
5.为bean注入bean
优化BeanFactory类 registerBeanDefinition只做bean的注册
/**
* @author Jalen.Deng
* @description 抽象bean工厂
* @date 2020/11/23 21:31
**/
public abstract class AbstractBeanFactory implements BeanFactory {
/**
*创建beanDefinitionMap来存储bean的实例
*/
private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
private final List<String> beanDefinitionNames = new ArrayList<String>();
@Override
public Object getBean(String name) throws Exception{
BeanDefinition beanDefinition = beanDefinitionMap.get(name);
if (beanDefinition == null) {
throw new IllegalArgumentException("No bean named " + name + " is defined");
}
Object bean = beanDefinition.getBean();
if (bean == null) {
bean = doCreateBean(beanDefinition);
}
return bean;
}
/**
* 注册bean到beanDefinitionMap中
* @param name
* @param beanDefinition
*/
@Override
public void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception {
beanDefinitionMap.put(name, beanDefinition);
beanDefinitionNames.add(name);
}
//初始化bean单例
public void preInstantiateSingletons() throws Exception {
for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) {
String beanName = (String) it.next();
getBean(beanName);
}
}
/**
* 初始化bean
* @param beanDefinition
* @return
*/
protected abstract Object doCreateBean(BeanDefinition beanDefinition) throws Exception;
}
public class AutowireCapableBeanFactory extends AbstractBeanFactory {
@Override
protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception {
Object bean = createBeanInstance(beanDefinition);
beanDefinition.setBean(bean);
applyPropertyValues(bean, beanDefinition);
return bean;
}
protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Exception {
for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) {
Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());
declaredField.setAccessible(true);
Object value = propertyValue.getValue();
//BeanReference为helloService,outputService
if(value instanceof BeanReference){
BeanReference beanReference = (BeanReference) value;
value = getBean(beanReference.getName());
}
declaredField.set(bean,value);
}
}
protected Object createBeanInstance(BeanDefinition beanDefinition) throws Exception {
return beanDefinition.getBeanClass().newInstance();
}
}
package com.dl.spring.xml;
/**
* @author Jalen.Deng
* @description xml解析bean定义
* @date 2020/11/24 14:32
**/
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
/**
*...省略之前相同的代码
**/
private void processProperty(Element ele, BeanDefinition beanDefinition) {
//其实就是解析 <property name="name" value="Hello World!"></property>
NodeList propertyNode = ele.getElementsByTagName("property");
for (int i = 0; i < propertyNode.getLength(); i++) {
Node node = propertyNode.item(i);
if (node instanceof Element) {
Element propertyEle = (Element) node;
String name = propertyEle.getAttribute("name");
String value = propertyEle.getAttribute("value");
/**
* <bean name="helloWorldService" class="com.dl.spring.HelloWorldService">
* <property name="outputService" ref="outputService"></property>
* </bean>
*/
if (value != null && value.length() > 0) {
beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, value));
} else {
String ref = propertyEle.getAttribute("ref");
//ref为helloWorldService,outputService,可以看出,加载顺序从上到下。
if (ref == null || ref.length() == 0) {
throw new IllegalArgumentException("Configuration problem: <property> element for property '"
+ name + "' must specify a ref or value");
}
BeanReference beanReference = new BeanReference(ref);
beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, beanReference));
}
}
}
}
}
package com.dl.spring;
/**
* @author Jalen.Deng
* @description bean引用,用于处理bean之间相互依赖
* @date 2020/11/25 9:01
**/
public class BeanReference {
private String name;
private Object bean;
public BeanReference(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object getBean() {
return bean;
}
public void setBean(Object bean) {
this.bean = bean;
}
}
package com.dl.spring;
import com.dl.spring.factory.AbstractBeanFactory;
import com.dl.spring.factory.AutowireCapableBeanFactory;
import com.dl.spring.factory.BeanFactory;
import com.dl.spring.io.ResourceLoader;
import com.dl.spring.xml.XmlBeanDefinitionReader;
import org.junit.Test;
import java.util.Map;
/**
* @author Jalen.Deng
* @description
* @date 2020/11/23 21:50
**/
public class BeanFactoryTest {
@Test
public void testLazy() throws Exception {
// 1.读取配置
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
// 2.初始化BeanFactory并注册bean
AbstractBeanFactory beanFactory = new AutowireCapableBeanFactory();
for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) {
beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());
}
// 3.获取bean
HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService");
helloWorldService.getOutputService().output("output");
helloWorldService.helloWorld();
}
@Test
public void testPreInstantiate() throws Exception {
// 1.读取配置
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
// 2.初始化BeanFactory并注册bean
AbstractBeanFactory beanFactory = new AutowireCapableBeanFactory();
for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) {
beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());
}
// 3.初始化bean
beanFactory.preInstantiateSingletons();
// 4.获取bean
HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService");
helloWorldService.helloWorld();
}
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!--为outputService注入helloWorldService -->
<bean name="outputService" class="com.dl.spring.OutputService">
<property name="helloWorldService" ref="helloWorldService"></property>
</bean>
<!--为helloWorldService注入outputService -->
<bean name="helloWorldService" class="com.dl.spring.HelloWorldService">
<property name="name" value="Hello World!"></property>
<property name="outputService" ref="outputService"></property>
</bean>
</beans>
对比Spring中的实现:DefaultListableBeanFactory#preInstantiateSingletons
这里补充一点:Spring是如何解决bean之间循环依赖的问题呢?
参考 https://www.jianshu.com/p/8bb67ca11831
https://blog.csdn.net/f641385712/article/details/92801300
这里我就说一点,Spring在实例化一个bean的时候,是首先递归的实例化其所依赖的所有bean,直到某个bean没有依赖其他bean,此时就会将该实例返回,然后反递归的将获取到的bean设置为上层bean的属性(A依赖B,B就是上层,也就是类A里面注入了B对象)。这也就是说,当我们使用构造器进行注入,A构造方法里new B对象,Spring是无法解决的,需要自己手动改代码以及换其他方式进行注入。
那么面试怎么回答呢?
①Spring是使用三级缓存解决循环依赖的,所谓三级缓存也就是三个map,单例对象缓存(存储可以直接使用的bean),半成品单例对象缓存(bean完成了实例化,但是没有注入属性),单例对象工厂缓存(存放 bean 工厂对象)。
②首先先去单例对象缓存取,取到了直接返回,没有的话就去半成品单例对象缓存取,取到了也直接返回,没有取到就去单例对象工厂缓存里,
开启allowEarlyReference=true这个配置通过singletonFactory.getObject()方法创建ObjectFactory类型的对象,然后“移动”到半成品单例对象缓存里,最后委托给doCreateBean去完成bean的初始化。
6使用ApplicationContext,在refresh()方法中初始化bean
package com.dl.spring.context;
import com.dl.spring.factory.AbstractBeanFactory;
import com.dl.spring.factory.BeanFactory;
/**
* @author Jalen.Deng
* @description 创建上下文对象接口
* @date 2020/11/24 14:43
**/
public interface ApplicationContext extends BeanFactory {
}
import com.dl.spring.factory.AbstractBeanFactory;
/**
* @author Jalen.Deng
* @description
* @date 2020/11/25 10:13
**/
public abstract class AbstractApplicationContext implements ApplicationContext {
protected AbstractBeanFactory beanFactory;
public AbstractApplicationContext(AbstractBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
public void refresh() throws Exception{
}
@Override
public Object getBean(String name) throws Exception {
return beanFactory.getBean(name);
}
}
package com.dl.spring.context;
import com.dl.spring.BeanDefinition;
import com.dl.spring.factory.AbstractBeanFactory;
import com.dl.spring.factory.AutowireCapableBeanFactory;
import com.dl.spring.io.ResourceLoader;
import com.dl.spring.xml.XmlBeanDefinitionReader;
import java.util.Map;
/**
* @author Jalen.Deng
* @description
* @date 2020/11/25 10:24
**/
public class ClassPathXmlApplicationContext extends AbstractApplicationContext {
private String configLocation;
public ClassPathXmlApplicationContext(String configLocation) throws Exception {
this(new AutowireCapableBeanFactory(), configLocation);
}
public ClassPathXmlApplicationContext(AbstractBeanFactory beanFactory, String configLocation) throws Exception {
super(beanFactory);
this.configLocation = configLocation;
refresh();
}
/**
* 使用refresh方法来注册bean
* @throws Exception
*/
@Override
public void refresh() throws Exception {
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
xmlBeanDefinitionReader.loadBeanDefinitions(configLocation);
for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) {
beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());
}
}
}
package com.dl.spring.factory;
import com.dl.spring.BeanDefinition;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Jalen.Deng
* @description 定义BeanFactory工厂接口
* @date 2020/11/23 20:36
**/
public interface BeanFactory {
/**
* 通过beanName获取bean实例
* @param name
* @return
*/
Object getBean(String name) throws Exception;
}
package com.dl.spring.context;
import com.dl.spring.HelloWorldService;
import org.junit.Test;
/**
* @author Jalen.Deng
* @description
* @date 2020/11/23 21:50
**/
public class ApplicationContextTest {
@Test
public void test() throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
HelloWorldService helloWorldService = (HelloWorldService) applicationContext.getBean("helloWorldService");
helloWorldService.helloWorld();
}
}
对比Spring中的实现:AbstractApplicationContext.refresh方法,非常核心且复杂的方法。
总结
参考
https://www.zybuluo.com/dugu9sword/note/382745#ioc-%E5%AE%B9%E5%99%A8%E7%9A%84%E5%AE%9E%E7%8E%B0