Spring源码:手写SpringIOC
文章目录
- 一、分析
- 二、实现
- 1、版本1:实现Bean注入IOC容器,并从容器中获取
- 1)定义BeanDefinition
- 2)定义BeanDefinition实现类
- 3)定义BeanDefinitionRegistry
- 4)定义Beanfactory
- 5)定义默认Beanfactory实现类
- 2、版本2:新增工厂关闭方法和支持单例bean
- 额外扩展:实现一个预构建BeanFactory,可以在系统启动时,提前初始化
- 3、版本3:支持获取指定名字的类型
- 4、版本4:获取指定类型的所有bean以及唯一bean
- 5、版本5:支持别名
- 三、最终完整版本
- BeanDefinition
- GenericBeanDefinition
- BeanDefinitionRegistry
- Beanfactory
- DefaultBeanFactory
- PreBuildBeanFactory
一、分析
IOC是Inversion of Control(控制反转)的缩写。它是一种软件设计原则,用于解耦组件之间的依赖关系。
也就是依赖对象的获取被反转了,从原来我们自己创建对象-》从IOC容器中获取,由它来管理。
这样的好处是什么?
代码更加简洁,不用自己去new对象
面向接口编程:解耦,易扩展,替换实现类;方便进行AOP编程
那么,你有啥思路?
其实可以这么理解,IOC容器=Bean工厂,Beanfactory会对外提供bean实例,所以需要提供getBean()方法;那么你要什么样的Bean,得描述告诉Bean工厂吧,所以需要一个Bean定义信息BeanDefinition,告诉它应该创建什么对象;我们定义的这些BeanDefinition存在哪?就需要一个注册器BeanDefinitionRegistry去维护这些信息
二、实现
1、版本1:实现Bean注入IOC容器,并从容器中获取
1)定义BeanDefinition
描述我们的bean是要单例还是多例,是通过什么去创建(直接new,还是通过工厂类创建),初始化以及销毁方法
import com.baomidou.mybatisplus.core.toolkit.StringUtils;/*** bean定义接口*/
public interface BeanDefinition {String SCOPE_SINGLETON = "singleton";String SCOPE_PROTOTYPE = "prototype";/*** 类*/Class<?> getBeanClass();void setBeanClass(Class<?> beanClass);/*** Scope*/void setScope(String scope);String getScope();/*** 是否单例*/boolean isSingleton();/*** 是否原型*/boolean isPrototype();/*** 工厂bean名*/String getFactoryBeanName();void setFactoryBeanName(String factoryBeanName);/*** 工厂方法名*/String getFactoryMethodName();void setFactoryMethodName(String factoryMethodName);/*** 初始化方法*/String getInitMethodName();void setInitMethodName(String initMethodName);/*** 销毁方法*/String getDestroyMethodName();void setDestroyMethodName(String destroyMethodName);/*** 是否为主要自动候选对象*/boolean isPrimary();void setPrimary(boolean primary);/*** 校验bean定义的合法性,BeanClass和FactoryMethodName只能存在一个,定义了FactoryMethodName,必须指定FactoryMethodName*/default boolean validate() {// 没定义类if (this.getBeanClass() == null) {// 工厂bean或工厂方法都没定义,则不合法if (StringUtils.isBlank(getFactoryBeanName()) || StringUtils.isBlank(getFactoryMethodName())) {return false;}}// 定义了类,又定义工厂bean,不合法if (this.getBeanClass() != null && StringUtils.isNotBlank(getFactoryBeanName())) {return false;}return true;}}
2)定义BeanDefinition实现类
定义一个通用实现类,实现BeanDefinition接口,对值的设置和获取
public class GenericBeanDefinition implements BeanDefinition {public static final String SCOPE_DEFAULT = "";private Class<?> beanClass;private String scope = SCOPE_DEFAULT;private String factoryBeanName;private String factoryMethodName;private String initMethodName;private String destroyMethodName;private boolean primary;@Overridepublic Class<?> getBeanClass() {return beanClass;}@Overridepublic void setBeanClass(Class<?> beanClass) {this.beanClass = beanClass;}@Overridepublic String getScope() {return scope;}@Overridepublic void setScope(String scope) {this.scope = scope;}/*** 默认是单例*/@Overridepublic boolean isSingleton() {return SCOPE_SINGLETON.equals(this.scope) || SCOPE_DEFAULT.equals(this.scope);}@Overridepublic boolean isPrototype() {return SCOPE_PROTOTYPE.equals(this.scope);}@Overridepublic String getFactoryBeanName() {return factoryBeanName;}@Overridepublic void setFactoryBeanName(String factoryBeanName) {this.factoryBeanName = factoryBeanName;}@Overridepublic String getFactoryMethodName() {return factoryMethodName;}@Overridepublic void setFactoryMethodName(String factoryMethodName) {this.factoryMethodName = factoryMethodName;}@Overridepublic String getInitMethodName() {return initMethodName;}@Overridepublic void setInitMethodName(String initMethodName) {this.initMethodName = initMethodName;}@Overridepublic String getDestroyMethodName() {return destroyMethodName;}@Overridepublic void setDestroyMethodName(String destroyMethodName) {this.destroyMethodName = destroyMethodName;}@Overridepublic boolean isPrimary() {return primary;}@Overridepublic void setPrimary(boolean primary) {this.primary = primary;}
}
3)定义BeanDefinitionRegistry
public interface BeanDefinitionRegistry {void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws Exception;BeanDefinition getBeanDefinition(String beanName);boolean containsBeanDefinition(String beanName);
}
4)定义Beanfactory
提供getBean方法,方便外部获取bean
public interface Beanfactory {Object getBean(String name) throws Exception;
}
5)定义默认Beanfactory实现类
实现BeanDefinitionRegistry和Beanfactory 接口,定义一个存储存储结构,存beanName和beanDefinition的映射关系;重写registerBeanDefinition和getBean等方法,定义了三种创建对象的方式:
- 直接new:new BeanClass
- 工厂静态方法:BeanClass.factoryMethodName()
- 工厂bean对象调用方法:new FactoryBeanName().factoryMethodName()
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;@Slf4j
public class DefaultBeanFactory implements BeanDefinitionRegistry, Beanfactory {// 存储结构:存beanName和beanDefinition的映射关系protected Map<String, BeanDefinition> beanDefintionMap = new ConcurrentHashMap<>(256);@Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws Exception {Objects.requireNonNull(beanName, "注册bean需要提供beanName");Objects.requireNonNull(beanDefinition, "注册bean需要提供beanDefinition");// 校验给入的bean是否合法if (!beanDefinition.validate()) {throw new RuntimeException("名字为[" + beanName + "] 的bean定义不合法:" + beanDefinition);}// Spring中默认是不可覆盖(抛异常),可通过参数 spring.main.allow-bean-definition-overriding: true 来允许覆盖if (this.containsBeanDefinition(beanName)) {throw new RuntimeException("名字为[" + beanName + "] 的bean定义已存在:" + this.getBeanDefinition(beanName));}beanDefintionMap.put(beanName, beanDefinition);}@Overridepublic BeanDefinition getBeanDefinition(String beanName) {return beanDefintionMap.get(beanName);}@Overridepublic boolean containsBeanDefinition(String beanName) {return beanDefintionMap.containsKey(beanName);}@Overridepublic Object getBean(String name) throws Exception {return this.doGetBean(name);}private Object doGetBean(String beanName) throws Exception {Objects.requireNonNull(beanName, "beanName不能为空");BeanDefinition bd = this.getBeanDefinition(beanName);Objects.requireNonNull(bd, "beanDefinition不能为空");Object instance = doCreateInstance(bd);return instance;}private Object doCreateInstance(BeanDefinition bd) throws Exception {Class<?> beanClass = bd.getBeanClass();Object instance = null;if (beanClass != null) {if (StringUtils.isBlank(bd.getFactoryMethodName())) {// 构造方法来构造对象instance = this.createInstanceByConstructor(bd);} else {// 静态工厂方法instance = this.createInstanceByStaticFactoryMethod(bd);}} else {// 工厂bean方式来构造对象instance = this.createInstanceByFactoryBean(bd);}// 执行初始化方法this.doInit(bd, instance);return instance;}// 构造方法来构造对象:new BeanClass()private Object createInstanceByConstructor(BeanDefinition bd) throws Exception {try {Class<?> beanClass = bd.getBeanClass();return beanClass.newInstance();} catch (SecurityException e) {log.error("创建bean的实例异常,beanDefinition:" + bd, e);throw e;}}// 静态工厂方法:BeanClass.factoryMethodName()private Object createInstanceByStaticFactoryMethod(BeanDefinition bd) throws Exception {Class<?> beanClass = bd.getBeanClass();Method m = beanClass.getMethod(bd.getFactoryMethodName(), null);return m.invoke(beanClass, null);}// 工厂bean方式来构造对象:new FactoryBeanName().factoryMethodName()private Object createInstanceByFactoryBean(BeanDefinition bd) throws Exception {Object factoryBean = this.doGetBean(bd.getFactoryBeanName());Class<?> factoryBeanClass = factoryBean.getClass();Method m = factoryBeanClass.getMethod(bd.getFactoryMethodName(), null);return m.invoke(factoryBean, null);}private void doInit(BeanDefinition bd, Object instance) throws Exception {// 执行初始化方法if (StringUtils.isNotBlank(bd.getInitMethodName())) {Method m = instance.getClass().getMethod(bd.getInitMethodName(), null);m.invoke(instance, null);}}
}
2、版本2:新增工厂关闭方法和支持单例bean
主要调整DefaultBeanFactory,实现了Closeable,重写了close方法,只针对单例Bean做了销毁处理,原型不用去销毁
,不知道会创建多少个对象,也得不到这些对象,不用去管,调整doGetBean方法支持单例模式。
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;
import java.io.Closeable;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;@Slf4j
public class DefaultBeanFactory implements BeanDefinitionRegistry, Beanfactory, Closeable {// 单例存储结构:存beanName和对应实例的映射关系private Map<String, Object> singletonBeanMap = new ConcurrentHashMap<>(256);// 省去其它代码...private Object doGetBean(String beanName) throws Exception {Objects.requireNonNull(beanName, "beanName不能为空");Object instance = singletonBeanMap.get(beanName);if (instance != null) {return instance;}BeanDefinition beanDefinition = this.getBeanDefinition(beanName);Objects.requireNonNull(beanDefinition, "beanDefinition不能为空");if (beanDefinition.isSingleton()) {synchronized (singletonBeanMap) {instance = singletonBeanMap.get(beanName);if (instance == null) {instance = doCreateInstance(beanDefinition);singletonBeanMap.put(beanName, instance);}}} else {instance = doCreateInstance(beanDefinition);}return instance;}@Overridepublic void close() {for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : beanDefintionMap.entrySet()) {String beanName = beanDefinitionEntry.getKey();BeanDefinition beanDefinition = beanDefinitionEntry.getValue();if (beanDefinition.isSingleton() && singletonBeanMap.containsKey(beanName)) {Object instance = this.singletonBeanMap.get(beanName);try {Method m = instance.getClass().getMethod(beanDefinition.getDestroyMethodName(), null);m.invoke(instance, null);} catch (Exception e) {log.error("执行名字为[" + beanName + "] 的bean销毁方法异常", e);}}}}
}
额外扩展:实现一个预构建BeanFactory,可以在系统启动时,提前初始化
import lombok.extern.slf4j.Slf4j;
import java.util.Map;@Slf4j
public class PreBuildBeanFactory extends DefaultBeanFactory{public void preInstantiateSingletons() throws Exception {synchronized (this.beanDefintionMap) {for (Map.Entry<String, BeanDefinition> entry : this.beanDefintionMap.entrySet()) {String name = entry.getKey();BeanDefinition beanDefinition = entry.getValue();if (beanDefinition.isSingleton()) {this.getBean(name);if (log.isDebugEnabled()) {log.debug("preInstantiate: name=" + name + " " + beanDefinition);}}}}}
}
3、版本3:支持获取指定名字的类型
主要调整Beanfactory和DefaultBeanFactory,Beanfactory新增一个getType方法,让子类去实现
public interface Beanfactory {Class<?> getType(String name) throws Exception;
}
重写getType方法
@Slf4j
public class DefaultBeanFactory implements BeanDefinitionRegistry, Beanfactory, Closeable {@Overridepublic Class<?> getType(String name) throws Exception {BeanDefinition beanDefinition = this.getBeanDefinition(name);Class<?> beanClass = beanDefinition.getBeanClass();if (beanClass != null) {// 如果是静态工厂方法,需要获取工厂创建的对象if (StringUtils.isNotBlank(beanDefinition.getFactoryMethodName())) {return beanClass.getDeclaredMethod(beanDefinition.getFactoryMethodName(), null).getReturnType();} else {return beanClass;}} else {// 其它情况是工厂方法的处理beanClass = getType(beanDefinition.getFactoryBeanName());return beanClass.getDeclaredMethod(beanDefinition.getFactoryMethodName(), null).getReturnType();}}@Overridepublic BeanDefinition getBeanDefinition(String beanName) {return beanDefintionMap.get(beanName);}
}
4、版本4:获取指定类型的所有bean以及唯一bean
一个type可能对应多个name,使用的存储结构如下:
private Map<Class<?>, Set<String>> typeNameMap = new ConcurrentHashMap<>(256);
调整DefaultBeanFactory的registerBeanDefinition,新增registerTypeNameMap方法,实现映射类型和beanName集合,支持当前类,父类,以及实现的接口,在Spring中,当你注入一个子类时,它会自动注入该子类实现的接口,而不会自动注入其继承的父类。
所以下面实现的registerSuperClassTypeNaemMap,是注入其继承的父类,可以选择不要。
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws Exception {Objects.requireNonNull(beanName, "注册bean需要提供beanName");Objects.requireNonNull(beanDefinition, "注册bean需要提供beanDefinition");// 校验给入的bean是否合法if (!beanDefinition.validate()) {throw new RuntimeException("名字为[" + beanName + "] 的bean定义不合法:" + beanDefinition);}// Spring中默认是不可覆盖(抛异常),可通过参数 spring.main.allow-bean-definition-overriding: true 来允许覆盖if (this.containsBeanDefinition(beanName)) {throw new RuntimeException("名字为[" + beanName + "] 的bean定义已存在:" + this.getBeanDefinition(beanName));}beanDefintionMap.put(beanName, beanDefinition);registerTypeNameMap();
}public void registerTypeNameMap() throws Exception {for (String name : beanDefintionMap.keySet()) {Class<?> type = this.getType(name);// 注册本类this.registerTypeNameMap(type, name);// 注册父类this.registerSuperClassTypeNaemMap(type, name);// 注册实现的接口this.registerInterfaceTypeNaemMap(type, name);}}private void registerTypeNameMap(Class<?> type, String name) {Set<String> beanNames = typeNameMap.get(type);if (beanNames == null) {beanNames = new HashSet<>();typeNameMap.put(type, beanNames);}beanNames.add(name);}private void registerSuperClassTypeNaemMap(Class<?> type, String name) {Class<?> superclass = type.getSuperclass();if (superclass != null && !superclass.equals(Object.class)) {// 注册本类this.registerTypeNameMap(superclass, name);// 注册父类this.registerSuperClassTypeNaemMap(superclass, name);// 注册实现的接口this.registerInterfaceTypeNaemMap(superclass, name);}}
Beanfactory新增两个方法如下:
public interface Beanfactory {<T> T getBean(Class<T> requiredType) throws Exception;<T> Map<String,T> getBeansOfType(Class<T> type)throws Exception;
}
DefaultBeanFactory 实现如下:
@Override
public <T> T getBean(Class<T> requiredType) throws Exception {Set<String> beanNames = typeNameMap.get(requiredType);if (null == beanNames) {return null;}if (beanNames.size() == 1) {String beanName = beanNames.iterator().next();return (T) this.getBean(beanName);} else {String primaryBeanName = null;for (String beanName : beanNames) {BeanDefinition beanDefinition = this.getBeanDefinition(beanName);if (beanDefinition != null && beanDefinition.isPrimary()) {if (primaryBeanName == null) {primaryBeanName = beanName;} else {throw new RuntimeException(requiredType + "类存在多个Primary,无法确定唯一一个Bean");}}}if (primaryBeanName != null) {return (T) this.getBean(primaryBeanName);} else {throw new RuntimeException(requiredType + "类未找到对应的Bean");}}
}@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) throws Exception {Set<String> beanNames = typeNameMap.get(type);if (null == beanNames) {return null;}Map<String, T> nameBeanMap = new HashMap<String, T>();for (String beanName : beanNames) {nameBeanMap.put(beanName, (T) this.getBean(beanName));}return nameBeanMap;
}
5、版本5:支持别名
三、最终完整版本
BeanDefinition
import com.baomidou.mybatisplus.core.toolkit.StringUtils;/*** bean定义接口*/
public interface BeanDefinition {String SCOPE_SINGLETON = "singleton";String SCOPE_PROTOTYPE = "prototype";/*** 类*/Class<?> getBeanClass();void setBeanClass(Class<?> beanClass);/*** Scope*/void setScope(String scope);String getScope();/*** 是否单例*/boolean isSingleton();/*** 是否原型*/boolean isPrototype();/*** 工厂bean名*/String getFactoryBeanName();void setFactoryBeanName(String factoryBeanName);/*** 工厂方法名*/String getFactoryMethodName();void setFactoryMethodName(String factoryMethodName);/*** 初始化方法*/String getInitMethodName();void setInitMethodName(String initMethodName);/*** 销毁方法*/String getDestroyMethodName();void setDestroyMethodName(String destroyMethodName);/*** 是否为主要自动候选对象*/boolean isPrimary();void setPrimary(boolean primary);/*** 校验bean定义的合法性,BeanClass和FactoryMethodName只能存在一个,定义了FactoryMethodName,必须指定FactoryMethodName*/default boolean validate() {// 没定义类if (this.getBeanClass() == null) {// 工厂bean或工厂方法都没定义,则不合法if (StringUtils.isBlank(getFactoryBeanName()) || StringUtils.isBlank(getFactoryMethodName())) {return false;}}// 定义了类,又定义工厂bean,不合法if (this.getBeanClass() != null && StringUtils.isNotBlank(getFactoryBeanName())) {return false;}return true;}}
GenericBeanDefinition
public class GenericBeanDefinition implements BeanDefinition {public static final String SCOPE_DEFAULT = "";private Class<?> beanClass;private String scope = SCOPE_DEFAULT;private String factoryBeanName;private String factoryMethodName;private String initMethodName;private String destroyMethodName;private boolean primary;@Overridepublic Class<?> getBeanClass() {return beanClass;}@Overridepublic void setBeanClass(Class<?> beanClass) {this.beanClass = beanClass;}@Overridepublic String getScope() {return scope;}@Overridepublic void setScope(String scope) {this.scope = scope;}/*** 默认是单例*/@Overridepublic boolean isSingleton() {return SCOPE_SINGLETON.equals(this.scope) || SCOPE_DEFAULT.equals(this.scope);}@Overridepublic boolean isPrototype() {return SCOPE_PROTOTYPE.equals(this.scope);}@Overridepublic String getFactoryBeanName() {return factoryBeanName;}@Overridepublic void setFactoryBeanName(String factoryBeanName) {this.factoryBeanName = factoryBeanName;}@Overridepublic String getFactoryMethodName() {return factoryMethodName;}@Overridepublic void setFactoryMethodName(String factoryMethodName) {this.factoryMethodName = factoryMethodName;}@Overridepublic String getInitMethodName() {return initMethodName;}@Overridepublic void setInitMethodName(String initMethodName) {this.initMethodName = initMethodName;}@Overridepublic String getDestroyMethodName() {return destroyMethodName;}@Overridepublic void setDestroyMethodName(String destroyMethodName) {this.destroyMethodName = destroyMethodName;}@Overridepublic boolean isPrimary() {return primary;}@Overridepublic void setPrimary(boolean primary) {this.primary = primary;}
}
BeanDefinitionRegistry
public interface BeanDefinitionRegistry {void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws Exception;BeanDefinition getBeanDefinition(String beanName);boolean containsBeanDefinition(String beanName);
}
Beanfactory
import java.util.Map;public interface Beanfactory {Object getBean(String name) throws Exception;Class<?> getType(String name) throws Exception;<T> T getBean(Class<T> requiredType) throws Exception;<T> Map<String,T> getBeansOfType(Class<T> type)throws Exception;
}
DefaultBeanFactory
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;import java.io.Closeable;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;@Slf4j
public class DefaultBeanFactory implements BeanDefinitionRegistry, Beanfactory, Closeable {// 存储结构:存beanName和beanDefinition的映射关系protected Map<String, BeanDefinition> beanDefintionMap = new ConcurrentHashMap<>(256);private Map<String, Object> singletonBeanMap = new ConcurrentHashMap<>(256);private Map<Class<?>, Set<String>> typeNameMap = new ConcurrentHashMap<>(256);@Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws Exception {Objects.requireNonNull(beanName, "注册bean需要提供beanName");Objects.requireNonNull(beanDefinition, "注册bean需要提供beanDefinition");// 校验给入的bean是否合法if (!beanDefinition.validate()) {throw new RuntimeException("名字为[" + beanName + "] 的bean定义不合法:" + beanDefinition);}// Spring中默认是不可覆盖(抛异常),可通过参数 spring.main.allow-bean-definition-overriding: true 来允许覆盖if (this.containsBeanDefinition(beanName)) {throw new RuntimeException("名字为[" + beanName + "] 的bean定义已存在:" + this.getBeanDefinition(beanName));}beanDefintionMap.put(beanName, beanDefinition);registerTypeNameMap();}public void registerTypeNameMap() throws Exception {for (String name : beanDefintionMap.keySet()) {Class<?> type = this.getType(name);// 注册本类this.registerTypeNameMap(type, name);// 注册父类:Spring不支持,我们这里也模拟注释掉,不开放// this.registerSuperClassTypeNaemMap(type, name);// 注册实现的接口this.registerInterfaceTypeNaemMap(type, name);}}private void registerTypeNameMap(Class<?> type, String name) {Set<String> beanNames = typeNameMap.get(type);if (beanNames == null) {beanNames = new HashSet<>();typeNameMap.put(type, beanNames);}beanNames.add(name);}private void registerSuperClassTypeNaemMap(Class<?> type, String name) {Class<?> superclass = type.getSuperclass();if (superclass != null && !superclass.equals(Object.class)) {// 注册本类this.registerTypeNameMap(superclass, name);// 注册父类this.registerSuperClassTypeNaemMap(superclass, name);// 注册实现的接口this.registerInterfaceTypeNaemMap(superclass, name);}}private void registerInterfaceTypeNaemMap(Class<?> type, String name) {Class<?>[] interfaces = type.getInterfaces();for (Class<?> anInterface : interfaces) {this.registerTypeNameMap(anInterface, name);this.registerInterfaceTypeNaemMap(anInterface, name);}}@Overridepublic BeanDefinition getBeanDefinition(String beanName) {return beanDefintionMap.get(beanName);}@Overridepublic boolean containsBeanDefinition(String beanName) {return beanDefintionMap.containsKey(beanName);}@Overridepublic Object getBean(String name) throws Exception {return this.doGetBean(name);}@Overridepublic Class<?> getType(String name) throws Exception {BeanDefinition beanDefinition = this.getBeanDefinition(name);Class<?> beanClass = beanDefinition.getBeanClass();if (beanClass != null) {// 如果是静态工厂方法,需要获取工厂创建的对象if (StringUtils.isNotBlank(beanDefinition.getFactoryMethodName())) {return beanClass.getDeclaredMethod(beanDefinition.getFactoryMethodName(), null).getReturnType();} else {return beanClass;}} else {// 其它情况是工厂方法的处理beanClass = getType(beanDefinition.getFactoryBeanName());return beanClass.getDeclaredMethod(beanDefinition.getFactoryMethodName(), null).getReturnType();}}@Overridepublic <T> T getBean(Class<T> requiredType) throws Exception {Set<String> beanNames = typeNameMap.get(requiredType);if (null == beanNames) {return null;}if (beanNames.size() == 1) {String beanName = beanNames.iterator().next();return (T) this.getBean(beanName);} else {String primaryBeanName = null;for (String beanName : beanNames) {BeanDefinition beanDefinition = this.getBeanDefinition(beanName);if (beanDefinition != null && beanDefinition.isPrimary()) {if (primaryBeanName == null) {primaryBeanName = beanName;} else {throw new RuntimeException(requiredType + "类存在多个Primary,无法确定唯一一个Bean");}}}if (primaryBeanName != null) {return (T) this.getBean(primaryBeanName);} else {throw new RuntimeException(requiredType + "类未找到对应的Bean");}}}@Overridepublic <T> Map<String, T> getBeansOfType(Class<T> type) throws Exception {Set<String> beanNames = typeNameMap.get(type);if (null == beanNames) {return null;}Map<String, T> nameBeanMap = new HashMap<String, T>();for (String beanName : beanNames) {nameBeanMap.put(beanName, (T) this.getBean(beanName));}return nameBeanMap;}private Object doGetBean(String beanName) throws Exception {Objects.requireNonNull(beanName, "beanName不能为空");Object instance = singletonBeanMap.get(beanName);if (instance != null) {return instance;}BeanDefinition beanDefinition = this.getBeanDefinition(beanName);Objects.requireNonNull(beanDefinition, "beanDefinition不能为空");if (beanDefinition.isSingleton()) {synchronized (singletonBeanMap) {instance = singletonBeanMap.get(beanName);if (instance == null) {instance = doCreateInstance(beanDefinition);singletonBeanMap.put(beanName, instance);}}} else {instance = doCreateInstance(beanDefinition);}return instance;}private Object doCreateInstance(BeanDefinition bd) throws Exception {Class<?> beanClass = bd.getBeanClass();Object instance = null;if (beanClass != null) {if (StringUtils.isBlank(bd.getFactoryMethodName())) {// 构造方法来构造对象instance = this.createInstanceByConstructor(bd);} else {// 静态工厂方法instance = this.createInstanceByStaticFactoryMethod(bd);}} else {// 工厂bean方式来构造对象instance = this.createInstanceByFactoryBean(bd);}// 执行初始化方法this.doInit(bd, instance);return instance;}// 构造方法来构造对象:new BeanClass()private Object createInstanceByConstructor(BeanDefinition bd) throws Exception {try {Class<?> beanClass = bd.getBeanClass();return beanClass.newInstance();} catch (SecurityException e) {log.error("创建bean的实例异常,beanDefinition:" + bd, e);throw e;}}// 静态工厂方法:BeanClass.factoryMethodName()private Object createInstanceByStaticFactoryMethod(BeanDefinition bd) throws Exception {Class<?> beanClass = bd.getBeanClass();Method m = beanClass.getMethod(bd.getFactoryMethodName(), null);return m.invoke(beanClass, null);}// 工厂bean方式来构造对象:new FactoryBeanName().factoryMethodName()private Object createInstanceByFactoryBean(BeanDefinition bd) throws Exception {Object factoryBean = this.doGetBean(bd.getFactoryBeanName());Class<?> factoryBeanClass = factoryBean.getClass();Method m = factoryBeanClass.getMethod(bd.getFactoryMethodName(), null);return m.invoke(factoryBean, null);}private void doInit(BeanDefinition bd, Object instance) throws Exception {// 执行初始化方法if (StringUtils.isNotBlank(bd.getInitMethodName())) {Method m = instance.getClass().getMethod(bd.getInitMethodName(), null);m.invoke(instance, null);}}@Overridepublic void close() {for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : beanDefintionMap.entrySet()) {String beanName = beanDefinitionEntry.getKey();BeanDefinition beanDefinition = beanDefinitionEntry.getValue();if (beanDefinition.isSingleton() && singletonBeanMap.containsKey(beanName)) {Object instance = this.singletonBeanMap.get(beanName);try {Method m = instance.getClass().getMethod(beanDefinition.getDestroyMethodName(), null);m.invoke(instance, null);} catch (Exception e) {log.error("执行名字为[" + beanName + "] 的bean销毁方法异常", e);}}}}
}
PreBuildBeanFactory
import lombok.extern.slf4j.Slf4j;
import java.util.Map;@Slf4j
public class PreBuildBeanFactory extends DefaultBeanFactory{public void preInstantiateSingletons() throws Exception {synchronized (this.beanDefintionMap) {for (Map.Entry<String, BeanDefinition> entry : this.beanDefintionMap.entrySet()) {String name = entry.getKey();BeanDefinition beanDefinition = entry.getValue();if (beanDefinition.isSingleton()) {this.getBean(name);if (log.isDebugEnabled()) {log.debug("preInstantiate: name=" + name + " " + beanDefinition);}}}}}
}
相关文章:

Spring源码:手写SpringIOC
文章目录 一、分析二、实现1、版本1:实现Bean注入IOC容器,并从容器中获取1)定义BeanDefinition2)定义BeanDefinition实现类3)定义BeanDefinitionRegistry4)定义Beanfactory5)定义默认Beanfactor…...

【软件设计师】程序猿需掌握的技能——数据流图
作为一个程序员,不仅要具备高水平的程序编码能力,还要是熟练掌握软件设计的方法和技术,具有一定的软件设计能力,一般包括软件分析设计图(常见的有数据流图,程序流程图,系统流程图,E-…...
17.3.1 像素处理
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 17.3.1 像素处理 C#处理图像,主要使用到Bitmap 类的 GetPixel方法和SetPixel方法。 Bitmap.GetPixel 方法:…...

白话微机:8.解释FPGA以及一些考研面试问题
一. 前言(更新世界观) 在“微机世界”,普通的城市(单片机)里,人又有一个别的名字叫做“数据”,人有0有1;人们也有住房,这些住房在这个世界叫做“存储器”;地上有路,这些路…...
Kubernetes基础(十八)-k8s存储对象Persistent Volume
1 什么是Persistent Volume? 在容器化应用中,Pod的生命周期是短暂的,当Pod终止时,其中的数据通常也会被销毁。为了解决这个问题,Kubernetes引入了Persistent Volume(PV)的概念。PV是集群中的一…...
用linux命令将文本格式文件转换为csv文件
文章目录 前言例: 总结 前言 用到linux命令awk 使用 awk 命令来将文本文件转换为 CSV 格式。假设你有一个以空格或制表符分隔的文本文件,以下是将其转换为 CSV 格式的命令: awk BEGIN { OFS"," } { print $1, $2, $3 } input.txt > outpu…...
C++中的binary_search函数详解
C中的std::binary_search函数详解 在C标准模板库(STL)中,std::binary_search是一个非常有用的函数,它可以在一个已排序的序列中查找一个特定的元素。这个函数的使用非常直观,但是了解其工作原理和一些注意事项可以帮助…...
程序员为什么不喜欢关电脑?我来回答
程序员为什么不喜欢关电脑? 主题: 你是否注意到,程序员们似乎从不关电脑?别以为他们是电脑上瘾,实则是有他们自己的原因!让我们一起揭秘背后的原因,看看程序员们真正的“英雄”本色!…...

波奇学Linux:动静态库
创建静态库 Makefile文件 mymath.c文件 mymath.h文件 编译main.c文件 gcc 编译时会把在系统目录中寻找头文件和库文件,文件不在系统目录中用参数 -I 头文件所在文件夹/ -L 库的地址文件夹 -l除去lib和后缀。 拷贝文件到系统目录即可不用参数 库的安装类似于把头文件…...
1723. 完成所有工作的最短时间
文章目录 题意思路代码 题意 题目链接 K个工人,一共jobs个任务,问怎样分配任务,最短的最长工人完成任务完成时间。 思路 DFS剪枝(最大单个工人jobs时间超过ans时间;有限空闲工人拿任务)模拟退火dp 代码…...

初始HTTP协议
一、http协议 1、http相关概念 互联网:是网络的网络,是所有类型网络的母集因特网:世界上最大的互联网网络。即因特网概念从属于互联网概念。习惯上,大家把连接在因特网上的计算机都成为主机。万维网:WWW(…...

C++ 位运算常用操作 二进制中1的个数
给定一个长度为 n 的数列,请你求出数列中每个数的二进制表示中 1 的个数。 输入格式 第一行包含整数 n 。 第二行包含 n 个整数,表示整个数列。 输出格式 共一行,包含 n 个整数,其中的第 i 个数表示数列中的第 i 个数的二进制表…...
大数据领域的数据仓库
在大数据领域,数据仓库(Data Warehouse)是一个用于存储、管理和分析大量数据的集中式系统。它从多个异构数据源收集数据,对数据进行清洗、转换和整合,然后将其存储在一个集中的位置,以支持复杂的查询、报告…...

sentinel的资源数据指标是如何采集
资源数据采集 之前的NodeSelectorSlot和ClusterBuilderSlot已经完成了对资源调用树的构建, 现在则是要对资源进行收集, 核心点就是这些资源数据是如何统计 LogSlot 作用: 记录异常请求日志, 用于故障排查 public class LogSlot extends AbstractLinkedProcessorSlot<Def…...

算法刷题:找到字符串中所有的字母异位词
找到字符串中所有的字母异位词 .题目链接题目详情题目解析算法原理滑动窗口流程图定义指针及变量进窗口判断出窗口更新结果 我的答案 . 题目链接 找到字符串中所有的字母异位词 题目详情 题目解析 所谓的异位词,就是一个单词中的字母,打乱顺序,重新排列得到的单词 如:abc-&g…...

【Java EE初阶十九】网络原理(四)
4. 数据链路层 数据链路层也有很多种协议,其中一个比较常见常用的,就是“以太网协议”(通过网线/光纤, 来通信所使用的协议叫做以太网协议,以太网是横跨数据链路层 物理层); 4.1 以太网数据帧格式 帧头 载荷(IP 数据…...
12.23 校招 实习 内推 面经
绿*泡*泡VX: neituijunsir 交流*裙 ,内推/实习/校招汇总表格 1、社招&校招 | 轻舟智航 社招 & 2024校招 社招&校招 | 轻舟智航 社招 & 2024校招 2、校招 | 成都精灵云科技2024校园招聘补录 校招 | 成都精灵云科技2024校园招聘补录 …...

FPGA转行ISP的探索之一:行业概览
ISP的行业位置 最近看到一个分析,说FPGA的从业者将来转向ISP(Image Signal Process图像信号处理)是个不错的选择,可以适应智能汽车、AI等领域。故而我查了一下ISP,对它大致有个概念。 传统的ISP对应的是相机公司&…...
Linux系统之部署网页小游戏合集网站
Linux系统之部署网页游戏合集网站 一、项目介绍1.1 项目介绍1.2 自定义配置方法二、本次实践介绍2.1 环境规划2.2 本次实践介绍三、检查本地环境3.1 检查操作系统版本3.2 检查当前yum仓库四、安装httpd软件4.1 检查yum仓库4.2 安装httpd软件4.3 启动httpd服务4.4 查看httpd服务…...

【白嫖8k买的机构vip教程】python(2):python_re模块
python之re模块 一、正则表达式 re模块是python独有的匹配字符串的模块,该模块中提供的很多功能是基于正则表达式实现的,而正则表达式是对字符串进行模糊匹配,提取自己需要的字符串部分,他对所有的语言都通用。注意…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...