Spring IOC(控制反转)是Spring框架的核心特性,彻底改变了Java对象管理的方式。传统开发中对象之间的引用需要通过new关键字手动创建,而Spring IOC将对象的创建和依赖管理交给容器统一处理,实现了控制权的反转

Spring IOC的实现用到了设计模式:简单工厂,他也是从简单工厂进化而来的,下面我们看看Spring的IOC是如何进化来的。

一、简单工厂模式

1.1 接口Fruit

1
2
3
4
5
6
7
8
9
10
11
12
package com.study.service;

/**
* 简单工厂模式
* 抽象接口
*
* @author Howe Hsiang
*/
public interface Fruit {
void eat();
}

1.2 实现类Apple和Orange

Apple实现类:

1
2
3
4
5
import com.study.service.Fruit;

/**
* 简单工厂模式
* 实现类Apple
  • 1
    * @author Howe Hsiang
    */
    1
    2
    3
    4
    5
    public class Apple implements Fruit {
    java
    @Override
    public void eat() {
    System.out.println("吃苹果");
    }

Orange实现类:

package com.study.service.Impl;

/**

  • 实现类Orange
    1
    2
    *
    */
    public class Orange implements Fruit {

System.out.println(“吃橘子”);

1
2
3
4
5
6
7
8
9
10
11
    }

#### 1.3 工厂类SimpleFactory

package com.study.controller;

import com.study.service.Impl.Apple;
import com.study.service.Impl.Orange;

/**
* 工厂类

*/

1
2
3
4
5
6
7
public class SimpleFactory {

public static Fruit getInstance(String className){

Fruit f = null;
if(className.equals("apple")){
f = new Apple();

}

1
2
if(className.endsWith("orange")){
f = new Orange();

}

1
return f;
}

}

1.4 测试类SimpleFactoryTest

import org.junit.Test;

/**

  • 测试简单工厂模式

    1
    2
    *
    */

    public class SimpleFactoryTest extends BaseTest {

    @Test
    public void getInstance() {

//苹果
Fruit apple = SimpleFactory.getInstance(“apple”);
apple.eat();

//橘子
Fruit orange = SimpleFactory.getInstance(“orange”);
orange.eat();

1
2
3
4
    }

}

二、反射+简单工厂模式

如果增加了水果,比如香蕉,那么在工厂类里面也要进行相关的修改了,这样不合理,而java的反射机制可以解决这个问题.

2.1 反射工厂类ReflexFactory

/**

  • 反射+简单工厂模式
  • 反射工厂类
    */

public class ReflexFactory {

try {
f = (Fruit) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}

}

2.2 测试类ReflexFactoryTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 测试反射+简单工厂模式
*
*/
public class ReflexFactoryTest extends BaseTest {

@Test

//苹果
Fruit apple = ReflexFactory.getInstance("com.study.service.Impl.Apple");

//橘子
Fruit orange = ReflexFactory.getInstance("com.study.service.Impl.Orange");
}

三、反射+简单工厂模式+xml配置文件

3.1 实例配置类PropertiesOperate

1
2
3
4
5
6
7
8
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Properties;

/**
* 反射+简单工厂模式+xml配置文件
* 实例配置类PropertiesOperate
  • */
1
2
3
4
5
6
7
8
9
10
11
12
13
public class PropertiesOperate {

private Properties pro = null;

String url = this.getClass().getResource("/").getPath();

private File file = new File(url+"fruit.properties");

public PropertiesOperate(){
this.pro = new Properties();
if(file.exists()){
try {
pro.loadFromXML(new FileInputStream(file));

}

1
2
}else{
this.save();

}

1
2
3
4
5
    private void save(){
this.pro.setProperty("apple","com.study.service.Impl.Apple");
this.pro.setProperty("orange", "com.study.service.Impl.Orange");
try {
this.pro.storeToXML(new FileOutputStream(this.file),"Fruit");

}

1
2
    public Properties getProperties(){
return this.pro;
}

}

3.2 测试类PropertiesOperateTest

/**

  • 测试反射+简单工厂模式+xml配置文件

    1
    2
    *
    */

    public class PropertiesOperateTest extends BaseTest {

    @Test
    public void getProperties(){

Properties pro=new PropertiesOperate().getProperties();

//苹果
Fruit apple = ReflexFactory.getInstance(pro.getProperty(“apple”));

//橘子
Fruit orange = ReflexFactory.getInstance(pro.getProperty(“orange”));

1
2
3

}

四、终极版本Spring IOC

以后如果要增加新的水果类,都要在这个配置文件里面登记。这时我们可以说配置文件可以控制程序的执行,现在看起来有点像spring的ioc了。下面我们来看看Spring IOC是如何实现的。

4.1 实体类Person和Grade

实体类Person:

package com.study.entity;

/**

  • 人类
    */
    public class Person {

    private String name;

    private int age;

    private Grade grade;

    public String getName() {

return name;
}

public void setName(String name) {

this.name = name;
}

public int getAge() {

return age;
}

public void setAge(int age) {

this.age = age;
}

public Grade getGrade() {

return grade;
}

public void setGrade(Grade grade) {

this.grade = grade;
}

实体类Grade:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 科目
*/
public class Grade {

private int math;

private int english;

public int getMath() {
return math;
}

public void setMath(int math) {
this.math = math;
}

public int getEnglish() {
return english;
}

public void setEnglish(int english) {
this.english = english;
}

#### 4.2 配置文件Bean.xml

<!--下面很多Bean-->

<!--第一个Bean,是一个Person类,id名字随便取,还要写上类的全名-->
<bean id="Person" class="com.study.entity.Person">
Howe Hsiang23
<!--同上-->
<bean id="Grade" class="com.study.entity.Grade">
9959

4.3 测试类SpringIocTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import com.study.controller.BaseTest;
import com.study.entity.Grade;
import com.study.entity.Person;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

/**
* 测试类
*/
public class SpringIocTest extends BaseTest {

@Test
public void getSpringIocInfo() {

//把input扔到工厂里面去,这个工厂就能为你提供实例了(装载配置文件)
BeanFactory factory = new ClassPathXmlApplicationContext("Bean.xml");

//你要一个叫Person的东西,那好,工厂就去找“Person"给你
Person person =(Person) factory.getBean("Person");
Grade grade=(Grade)factory.getBean("Grade");

//person可以调用里面相关的方法,就相当于new了一个Person一样
System.out.println(
"姓名:"+person.getName()+ "; " +
"年龄:"+person.getAge() + "; " +
"数学成绩:"+grade.getMath()+ "; " +
"英语成绩:"+grade.getEnglish());
}

}

五、其他

1、关于Spring读取配置文件的方法

applicationcontext—

FileSystemXmlApplicationContext—这个方法是从文件绝对路径加载配置文

1
ClassPathXmlApplicationContext---这个方法是从classpath下加载配置文件(适合于相对路径方式加载)

XmlWebApplicationContext—-专为web工程定制的方法,推荐Web项目中使用。

beanfactory—

1
ClassPathResource --- 从系统的类路径中加载

FileSystemResource — 从文件系统加载,比如说自己指定配置文件的全路径

InputStreamResource — 从输入流中加载

ServletContextResource — 从Servlet 上下文环境中加载

UrlResource — 从指定的Url加载


2、BeanFactory和ApplicationContext的区别

ApplicationContext接口,它由BeanFactory接口派生而来,因而提供BeanFactory所有的功能。
ApplicationContext以一种更向面向框架的方式工作以及对上下文进行分层和实现继承,ApplicationContext包还提供了以下的功能:

• MessageSource, 提供国际化的消息访问

• 资源访问,如URL和文件

• 事件传播

• 载入多个(有继承关系)上下文,使得每一个上下文都专注于一个特定的层次,比如应用的web层

最主要的就是BeanFactory延迟加载,当使用到getBean的时候才会抛异常,而ApplicationContext在刚开始启动加载的时候就会抛出异常,这样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用ApplicationContext。

1
*注:* [SpringIOC详解](https://github.com/Hosiang1026/springioc)

本文标题: Spring框架核心IOC开发

发布时间: 2019年03月25日 00:00

最后更新: 2026年09月16日 05:40

原始链接: https://haoxiang.eu.org/92e11628/

版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0许可协议,转载请注明出处!

× 喜欢就赞赏一下呗!
打赏二维码