ioc的简单实现

ioc的简单实现
│  
│  
└─文件目录
    │  BeanReference.java----------------------------对Bean的封装
    │  
    ├─beans
    │  │  AbstractBeanDefinitionReader.java----------抽象类
    │  │  BeanDefinition.java------------------------
    │  │  BeanDefinitionReader.java------------------接口
    │  │  PropertyValue.java-------------------------
    │  │  PropertyValues.java------------------------
    │  │  
    │  ├─factory
    │  │      AbstractBeanFactory.java---------------抽象类,实现BeanFactory接口
    │  │      AutowireCapableBeanFactory.java--------
    │  │      BeanFactory.java-----------------------接口,bean的容器
    │  │      
    │  ├─io
    │  │      Resource.java--------------------------接口
    │  │      ResourceLoader.java--------------------
    │  │      UrlResource.java-----------------------
    │  │      
    │  └─xml
    │          XmlBeanDefinitionReader.java----------
    │          
    └─context
            AbstractApplicationContext.java----------
            ApplicationContext.java------------------
            ClassPathXmlApplicationContext.java------
            






bean包下


BeanDefinitionReader接口
定义loadBeanDefinitions(String location)方法,从配置文件中导入BeanDefinitions


AbstractBeanDefinitionReader
实现BeanDefinitionReader接口
封装了Map<String,BeanDefinition> registry;ResourceLoader resourceLoader;
有参构造方法AbstractBeanDefinitionReader(ResourceLoader resourceLoader),初始化两个类变量 registry 和 resourceLoader
两个类变量的get方法


BeanDefinition
bean的内容及元数据,保存在BeanFactory中,包装bean的实体
类变量有
Object bean; //实例化的bean
Class beanClass; //bean的字节码
String beanClassName; //bean的全限定名
PropertyValues propertyValues = new PropertyValues(); 
setter & getter ...
其中setBeanClassName方法里面用反射实例化class。this.beanClass = Class.forName(beanClassName);


PropertyValues
final List<PropertyValue> propertyValueList 
包装一个对象所有的PropertyValue。为什么封装而不是直接用List?因为可以封装一些操作。
addPropertyValue(PropertyValue pv);list.add之前可以对于重复propertyName进行判断,直接用list没法做到


PropertyValue
用于bean的属性注入
类变量
final String name;                    
final Object value;


bean包下的Factory包:


BeanFactory
接口,bean的容器,定义了根据name获取bean的方法getBean(String name)


AbstractBeanFactory
抽象类,实现BeanFactory接口
封装beanDefinitionMap(类型为ConcurrentHashMap)、beanDefinitionNames(类型为ArrayList)
重写BeanFactory接口 getBean 方法
从beanDefinitionMap里根据name获取BeanDefinition,从BeanDefinition里获取Bean,如果bean为null就创建(doCreateBean(beanDefinition));
方法registerBeanDefinition(String name, BeanDefinition beanDefinition)
注册bean,把name放入ArrayList,把BeanDefinition放入beanDefinitionMap
方法preInstantiateSingletons()
遍历beanDefinitionNames,调用getBean方法
哪里调用的?
定义抽象方法 doCreateBean(BeanDefinition beanDefinition)
需要子类实现


AutowireCapableBeanFactory
继承抽象类 AbstractBeanFactory
方法 applyPropertyValues(Object bean, BeanDefinition mbd)
从 beanDefinition 里获取封装的ArrayList对象获取对象里ArrayList遍历每一个 PropertyValue
通过参数bean获取class对象,获取名为 propertyValue.getName() 的字段
设置字段的 accessible 标志为 true
获取propertyValue封装的object
如果是BeanReference类或者是BeanReference的子类的一个实例,
强制转换成 BeanReference
调用父类的 getBean 方法
设置字段的bean值为从 propertyValue 获取的value???(有疑问,什么意思,不太理解)
方法 createBeanInstance(BeanDefinition beanDefinition)
从 beanDefinition 里获取 beanClass ,然后 newInstance() ,实例化对象
重写抽象方法 doCreateBean
调用 createBeanInstance
把初始化出来的bean设置回 beanDefinition
调用 applyPropertyValues




bean包下的io包:


Resource
接口
spring内部定位资源的接口
定义方法 getInputStream(); 获取输入流




UrlResource
实现Resource接口
类变量 
final URL url;
重写父类方法getInputStream();使用URLConnection获取输入流


ResourceLoader
方法 getResource(String location)
先通过this.getClass().getClassLoader().getResource(location);ClassLorder类的方法:URL getResource(String name) 查找具有给定名称的资源
将返回的URL作为参数实例化UrlResource类

外部直接调用ResourceLoader来加载xml文件,然后调用解析xml文件的类就行了


bean包下的xml包:
XmlBeanDefinitionReader
实现了 AbstractBeanDefinitionReader 类
重写了 BeanDefinitionReader 接口的 loadBeanDefinitions 方法
调用父类的 getResourceLoader方法获取ResourceLoader然后resourceLoader.getResource(location).getInputStream();获取输入流
doLoadBeanDefinitions(InputStream inputStream) 使用JDK自带的工具解析xml,略过此过程。。。




context包:


ApplicationContext
接口,继承 BeanFactory 接口


AbstractApplicationContext
抽象类,实现 ApplicationContext 接口
依赖 AbstractBeanFactory 
重写 getBean 方法,调用 AbstractBeanFactory 的 getBean 方法
refresh() 为空,应该是简化了,需要后续实现

ClassPathXmlApplicationContext
感觉这个类比较重要
继承AbstractApplicationContext
两个构造函数挺有意思
public ClassPathXmlApplicationContext(String configLocation) throws Exception {
this(configLocation, new AutowireCapableBeanFactory());
}


public ClassPathXmlApplicationContext(String configLocation, AbstractBeanFactory beanFactory) throws Exception {
super(beanFactory);
this.configLocation = configLocation;
refresh();
}


重写了父类的 refresh 方法
初始化 XmlBeanDefinitionReader ,调用它的 loadBeanDefinitions 方法
调用 xmlBeanDefinitionReader.getRegistry() 方法,其实是调用其父类 AbstractBeanDefinitionReader 的方法,获取父类 AbstractBeanDefinitionReader 中封装的 Map<String,BeanDefinition> registry
然后调用 Map 类的 entrySet() 方法, ----返回此映射中包含的映射关系的 Set 视图?----返回Set<Map.Entry<K, V>>
遍历 Map.Entry<String, BeanDefinition> beanDefinitionEntry
调用 beanFactory 的 registerBeanDefinition 方法,注册 Bean ...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值