1、Spring核心容器
![spring 手写简单的IOC_第1张图片](http://img.e-com-net.com/image/info8/32bbae2b84684a96a6984e8c8f526ac3.jpg)
是spring核心模块,包含【控制反转】和【依赖注入】。
BeanFactory使用控制反转对应用程序的配置和依赖性规范与实际应用程序分离。
BeanFactory属于【延时加载】,实例化容器不会实例化bean,而是在bean使用时,才会对bean实例化与依赖关系的装配
//不会实例化,不会调用构造方法
BeanFactory context = new XmlBeanFactory(new ClassPathResource("application.xml"));
//使用时实例化,调用构造方法
UserService userService = context.getBean("userService", UserService.class);
构架于核心模块之上,【扩展】了BeanFactory,添加生命周期、框架事件体系、资源加载透明化(还包括了邮件访问、远程访问、任务调度)
ApplicationContext是核心接口,【继承BeanFactory】,但实例化容器之后会【自动】对所有的单实例bean实例化和依赖关系的装配
//会实例化bean,调用其构造方法
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
【IOC容器】和【IOC子容器】的扩展--springMvc
【类管理组件】和【classpath扫描组件】--扫描注解
同一表达式语言(EL)的扩展模块,查询、管理运行中的对象,方便的调用对象方法。
2、IOC分析
1)BeanFactory(管理bean及其关系)
![spring 手写简单的IOC_第2张图片](http://img.e-com-net.com/image/info8/2f00265242c748c383d2b9c1a489fb47.jpg)
IOC容器【简单工厂+配置文件】
--【实现类】DefaultListableBeanFactory
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1) throws BeansException;
boolean containsBean(String var1);
boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
}
![spring 手写简单的IOC_第3张图片](http://img.e-com-net.com/image/info8/6ef633be0a9b4f3482d44436517bf05a.jpg)
2)BeanDefinition(封装xml中的标签)
![spring 手写简单的IOC_第4张图片](http://img.e-com-net.com/image/info8/96bbd4edfac54f3aabdc9bed4381377e.jpg)
3)BeanDefinitionReader(xml标签解析)
![spring 手写简单的IOC_第5张图片](http://img.e-com-net.com/image/info8/6fcfe7c5e58741b4a3242998df10b8c8.jpg)
public interface BeanDefinitionReader {
BeanDefinitionRegistry getRegistry();
int loadBeanDefinitions(Resource var1) throws BeanDefinitionStoreException;
int loadBeanDefinitions(Resource... var1) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String var1) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String... var1) throws BeanDefinitionStoreException;
}
4)BeanDefinitionRegistry(存储所有bean)
![spring 手写简单的IOC_第6张图片](http://img.e-com-net.com/image/info8/d1a50b0c5cbc4a1cb30f2bf081c17e40.jpg)
public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String var1);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String var1);
}
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
private final Map<String, BeanDefinition> beanDefinitionMap;
public DefaultListableBeanFactory() {
this.beanDefinitionMap = new ConcurrentHashMap(256);
}
}
5)创建容器(refresh方法)
ClassPathXmlApplicationContext对Bean对象的装再是从refresh()方法开始的,是一个模板方法,规定了IOC执行流程,其逻辑交由子类实现。
他对Bean资源的载入,ClassPathXmlApplicationContext通过调用父类的AbstractApplicationContext的refresh()方法启动整个IOC容器对Bean的装载过程。
3、手写IOC
![spring 手写简单的IOC_第7张图片](http://img.e-com-net.com/image/info8/b2fd45fc6d4c4b2d9dc6f08d1915cc1d.jpg)
<--! maven 依赖-->
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.24version>
<scope>compilescope>
dependency>
<dependency>
<groupId>dom4jgroupId>
<artifactId>dom4jartifactId>
<version>1.1version>
dependency>
1)定义Bean相关的POJO类
① PropertyValue类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PropertyValue {
private String name;
private String ref;
private String value;
}
② PropertyValues类
@Data
public class MutablePropertyValues implements Iterable<PropertyValue>{
private final List<PropertyValue> propertyValueList;
public MutablePropertyValues() {
this.propertyValueList = new ArrayList<>();
}
public MutablePropertyValues(List<PropertyValue> propertyValueList) {
if (propertyValueList == null){
this.propertyValueList = new ArrayList<>();
}else {
this.propertyValueList = propertyValueList;
}
}
@Override
public Iterator<PropertyValue> iterator() {
return propertyValueList.iterator();
}
public PropertyValue[] getPropertyValueList(){
return propertyValueList.toArray(new PropertyValue[0]);
}
public PropertyValue getPropertyValue(String name){
return propertyValueList.stream().filter(t->name.equals(t.getName())).findFirst().orElse(null);
}
public boolean isContain(String name){
return getPropertyValue(name) != null;
}
public boolean isEmpty(){
return propertyValueList.isEmpty();
}
public MutablePropertyValues addPropertyValue(PropertyValue propertyValue){
List<String> list = propertyValueList.stream()
.map(PropertyValue::getName)
.filter(t -> propertyValue.getValue().equals(t))
.collect(Collectors.toList());
if (!list.isEmpty()){
throw new RuntimeException("bean名称重复");
}
propertyValueList.add(propertyValue);
return this;
}
}
③ BeanDefinition类
@Data
public class BeanDefinition {
private String id;
public String clazz;
private MutablePropertyValues mutablePropertyValues;
public BeanDefinition(){
mutablePropertyValues = new MutablePropertyValues();
}
}
2)定义注册表相关的类
① BeanDefinitionRegiesty接口
public interface BeanDefinitionRegistry {
void registryBeanDefinition(String beanName, BeanDefinition beanDefinition);
void removeBeanDefinition(String beanName);
BeanDefinition getBeanDefinition(String beanName);
boolean containBeanDefinition(String beanName);
int getBeanDefinitionCount();
String[] getBeanDefinitionNames();
}
② SimpleBeanDefinitionRegiesty实现类
public class SimpleBeanDefinitionRegistry implements BeanDefinitionRegistry{
private Map<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
@Override
public void registryBeanDefinition(String beanName, BeanDefinition beanDefinition) {
beanDefinitionMap.put(beanName, beanDefinition);
}
@Override
public void removeBeanDefinition(String beanName) {
beanDefinitionMap.remove(beanName);
}
@Override
public BeanDefinition getBeanDefinition(String beanName) {
return beanDefinitionMap.get(beanName);
}
@Override
public boolean containBeanDefinition(String beanName) {
return beanDefinitionMap.containsKey(beanName);
}
@Override
public int getBeanDefinitionCount() {
return beanDefinitionMap.size();
}
@Override
public String[] getBeanDefinitionNames() {
return beanDefinitionMap.keySet().toArray(new String[0]);
}
}
3)定义解释器相关的类
① BeanDefinfitionReader接口
public interface BeanDefinitionReader {
BeanDefinitionRegistry getRegistry();
void loadBeanDefinitions(String configLocation) throws Exception;
}
② XmlBeanDefinitionReader实现类
public class XmlBeanDefinitionReader implements BeanDefinitionReader {
private BeanDefinitionRegistry beanDefinitionRegistry;
public XmlBeanDefinitionReader() {
this.beanDefinitionRegistry = new SimpleBeanDefinitionRegistry();
}
@Override
public BeanDefinitionRegistry getRegistry() {
return beanDefinitionRegistry;
}
@Override
public void loadBeanDefinitions(String configLocation) throws Exception {
SAXReader saxReader = new SAXReader();
InputStream stream = XmlBeanDefinitionReader.class.getClassLoader().getResourceAsStream(configLocation);
Document document = saxReader.read(stream);
Element beans = document.getRootElement();
List<Element> bean = beans.elements("bean");
for (Element element : bean) {
BeanDefinition beanDefinition = new BeanDefinition();
String id = element.attributeValue("id");
beanDefinition.setId(id);
beanDefinition.setClazz(element.attributeValue("class"));
MutablePropertyValues propertyValues = new MutablePropertyValues();
List<Element> properties = element.elements("property");
for (Element property : properties) {
String name = property.attributeValue("name");
String ref = property.attributeValue("ref");
String value = property.attributeValue("value");
PropertyValue propertyValue = new PropertyValue(name, ref, value);
propertyValues.addPropertyValue(propertyValue);
}
beanDefinition.setMutablePropertyValues(propertyValues);
beanDefinitionRegistry.registryBeanDefinition(id, beanDefinition);
}
}
}
4)IOC相关类
① BeanFactory 接口
public interface BeanFactory {
Object getBean(String name) throws Exception;
<T> T getBean(String name, Class<? extends T> type) throws Exception;
}
② ApplicationContext 接口
public interface ApplicationContext extends BeanFactory {
void refresh() throws Exception;
}
③ AbstractApplicationContext 接口
public abstract class AbstractApplicationContext implements ApplicationContext {
protected BeanDefinitionReader beanDefinitionReader;
protected Map<String, Object> singletonObject = new ConcurrentHashMap<>();
protected String configLocation;
@Override
public void refresh() throws Exception {
beanDefinitionReader.loadBeanDefinitions(configLocation);
finishBeanInitialization();
}
private void finishBeanInitialization() throws Exception{
BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
String[] beanNames = registry.getBeanDefinitionNames();
for (String beanName : beanNames) {
getBean(beanName);
}
}
}
④ ClassPathXmlApplicationContext 类
public class ClassPathXmlApplicationContext extends AbstractApplicationContext{
public ClassPathXmlApplicationContext(String configLocation) {
this.configLocation = configLocation;
beanDefinitionReader = new XmlBeanDefinitionReader();
try {
this.refresh();
}catch (Exception e){
throw new RuntimeException(e);
}
}
@Override
public Object getBean(String beanName) throws Exception {
Object obj = singletonObject.get(beanName);
if (obj != null){
return obj;
}
BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
String className = beanDefinition.getClazz();
Class clazz = Class.forName(className);
Object beanObj = clazz.newInstance();
MutablePropertyValues mutablePropertyValues = beanDefinition.getMutablePropertyValues();
for (PropertyValue property : mutablePropertyValues) {
String name = property.getName();
String ref = property.getRef();
String value = property.getValue();
if (ref!=null && !"".equals(ref)){
Object bean = getBean(ref);
String methodName = StringUtils.getSetterName(name);
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.getName().equals(methodName)){
method.invoke(beanObj, bean);
break;
}
}
}
if (value!=null && !"".equals(value)){
String methodName = StringUtils.getSetterName(name);
Method methods = clazz.getMethod(methodName, String.class);
methods.invoke(beanObj, value);
}
}
singletonObject.put(beanName, beanObj);
return beanObj;
}
@Override
public <T> T getBean(String name, Class<? extends T> type) throws Exception {
Object bean = getBean(name);
if (bean == null){
return null;
}
return type.cast(bean);
}
}