写在前面
本文看下如何定义IOC部分内容。
源码 。
1:基础实现
先来定义要通过ioc管理的bean,如下:
java
public class AServiceImpl implements AService {
public void sayHello() {
System.out.println("a service 1 say hello");
}
}
为了实现IOC,我们需要先来定义一个xml文件,来表达bean信息,如下:
xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id = "aservice" class = "com.hc.minispring.ioc.one.v1.test.AServiceImpl"></bean>
</beans>
定义对应xml的bean定义类,beandefinition:
java
package com.hc.minispring.ioc.one.v1;
import lombok.Data;
/**
* bean外部定义的内存映射类
*/
@Data
public class BeanDefinition {
private String id;
private String className;
public BeanDefinition(String id, String className) {
this.id = id;
this.className = className;
}
}
接着定义一个类来读取xml信息,并创建bean信息:
java
public class ClassPathXmlApplicationContext {
private List<BeanDefinition> beanDefinitions = new ArrayList<>();
private Map<String, Object> singletons = new HashMap<>();
//构造器获取外部配置,解析出Bean的定义,形成内存映像
public ClassPathXmlApplicationContext(String fileName) {
this.readXml(fileName);
this.instanceBeans();
}
private void readXml(String fileName) {
// ... 具体参看源码
}
//利用反射创建Bean实例,并存储在singletons中
private void instanceBeans() {
for (BeanDefinition beanDefinition : beanDefinitions) {
// ... 具体参看源码
}
}
//这是对外的一个方法,让外部程序从容器中获取Bean实例,会逐步演化成核心方法
public Object getBean(String beanName) {
return singletons.get(beanName);
}
}
接着我们来写一个测试类:
java
public class Test1 {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new
ClassPathXmlApplicationContext("v1/beans.xml");
AService aService = (AService)ctx.getBean("aservice");
aService.sayHello();
}
运行:
a service 1 say hello
Process finished with exit code 0
2:根据单一职责改造
面向对象设计原则中的单一原则是一个很重要的原则,它不会让一个类的职责过于繁重,从而让类变得复杂,最终让整体的程序变得维护成本和扩展的成本很高,所以我们接下来对ClassPathXmlApplicationContext进行一番改造。首先对于xml这类定义bean定义的信息,我们将其抽象为资源,而数据是核心,所以我们可以定义core包来放这部分内容,定义Resource接口来代表资源:
java
/**
* 基础资源对应的接口,如xml,注解类等
*/
public interface Resource extends Iterator<Object>{
}
接着我们定义beans目录,放bean相关的内容,如beandifinitionreader(读取resource为bean定义),beandefinition(bean定义),beanfactory(bean的工厂),这样通过beandifinitionreader读取resource为beandifinition,然后通过beanfacotry读取beandifinition信息,创建并维护bean信息。最后在定义一个context目录,来作为整合的入口,使用上述的这些独立的功能完成bean信息的维护,定义类ClassPathXmlApplicationContext:
java
/**
* 集大成者的类,暴漏给用户使用
*/
public class ClassPathXmlApplicationContext implements BeanFactory {
BeanFactory beanFactory;
public ClassPathXmlApplicationContext(String fileName) {
Resource res = new ClassPathXmlResource(fileName);
BeanFactory bf = new SimpleBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
reader.loadBeanDefinitions(res);
this.beanFactory = bf;
}
@Override
public Object getBean(String beanName) throws NoSuchBeanDefinitionException {
return this.beanFactory.getBean(beanName);
}
@Override
public void registerBeanDefinition(BeanDefinition bd) {
this.beanFactory.registerBeanDefinition(bd);
}
}
最终如下:

测试:
java
public class Test1 {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new
ClassPathXmlApplicationContext("v2/beans.xml");
AService aService = (AService)ctx.getBean("aservice");
aService.sayHello();
}
}
运行:
a service 1 say hello v2
Process finished with exit code 0
这样我们就按照单一职责将不同的功能使用不同的类实现,并且将一类功能按照包的方式组织在了一起,大概如下:
core包:
资源相关
beans包:
bean处理相关
context包:
用户入口,统筹
