Spring ioc inversion of control. Spring的反转控制,是spring所有框架的实现核心,它提供了一个新的思路,对于框架和类依赖的解耦,实体之间不再有相应的引用,只需要通过接口进行定义,然后运行时/启动时加载相应的实现类即可。
目标:
1、 解耦合,简化程序的复杂程度,使程序依赖于框架而非类库包。
2、 提高性能,单例bean的实现,大大消减了示例创建和消灭的性能开销。
3、 简化开发,提高开发效率
4、 提高代码复用率,充分使用oo设计思想
5、 增加代码的可移植性。
思路:
1、 bean的管理外化,通过非javacode方式进行配置,可选的方式有:属性文件,xml,注解,ejb的jar包或war包,数据库等。
2、 bean的创建,依赖于rt包中的bean包,也可以由自己个性实现,基本上是通过反射实现的jdk代理和cglib代理。
3、 bean的存储由一个map,key为bean的name,value是bean的实例,因为对于程序运行时,是只读的map,所以不存在线程安全问题,可以直接用hashmap
具体实现:
BeanContainer:
public class BeanContainer {
private static final BeanContainer container1 = new BeanContainer();
private final Map container;
private BeanContainer(){
this.container = new HashMap();
}
/**
*必须是单例,否则会获取不到
* @return
*/
public static BeanContainer getIntance(){
return container1;
}
/**
* 增加bean ,将实例放在容器中,一般有框架加载
* @param name
* @param bean
* @return
*/
public Object addBean(String name , Object bean){
container.put(name,bean);
return bean;
}
/**
* 获取bean,是ioc外经常使用的方法
* @param name
* @return
*/
public Object getBean(String name){
Object obj = container.get(name);
return obj;
}
public Object removeBean(String name){
return container.remove(name);
}
}
BeanCreator:
public class BeanCreator {
private ClassLoader classLoader = ClassLoader.getSystemClassLoader();
/**
* 此处为简单的实例实现,可以通过不同的方式进行实例化,该方法只是用了classload的方法
* @param path
* @return
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public Object createBean(String path) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Object obj = classLoader.loadClass(path).newInstance();
return obj;
}
}
BeanManager:
public class BeanManager {
/**
* 将bean的配置信息加载进来,本次使用的是propeerties,可以自行更换其他的方式
* @return
* @throws IOException
*/
public Properties getProperties() throws IOException {
FileInputStream fis = new FileInputStream("eureka-server\\src\\test\\java\\com\\example\\ioc\\test.properties");
Properties props = new Properties();
props.load(fis);
return props;
}
/**
* 加载所有配置过的bean,进入容器
* @throws IOException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws ClassNotFoundException
*/
public void loadBean() throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException {
BeanContainer container = BeanContainer.getIntance();
BeanCreator creator = new BeanCreator();
Properties props = getProperties();
container.addBean(props.getProperty("name"),creator.createBean(props.getProperty("path")));
}
}
test.properties:
name=testbean
path=com.example.ioc.TestBean
测试类:
BeanManager manager = new BeanManager();
BeanContainer container = BeanContainer.getIntance();
try {
manager.loadBean();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
TestBean bean = (TestBean).getBean("testbean");
bean.test();
从上例可以看到,所有的bean加载由框架完成,我们在使用中,只需要都用getbean方法,就可以拿到实例,因此整个都是单例的过程。后面我们也可以丰富一下选项,比如懒加载,比如单实例和多实例切换等,这些都可以通过改变createbean的实现来完成。
简单来说,以上的例子并没有表现出oo的设计思想,只是说明了整个简单的实现过程,设计上,ioc使用了接口加组合的方式,使得整体框架更加的灵活多变,更能适应基础框架的扩展。