以前对象之间的引用是通过new来调用实现,有了Spring IOC,我们可以把对象之间的引用交给他来管理,这样就把控制权交给了Spring,所以就叫做控制反转。

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

一、简单工厂模式
1.1 接口Fruit
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.study.service;
public interface Fruit { void eat(); }
|
1.2 实现类Apple和Orange
Apple实现类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
import com.study.service.Fruit;
public class Apple implements Fruit {
@Override public void eat() { System.out.println("吃苹果"); } }
|
Orange实现类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.study.service.Impl;
import com.study.service.Fruit;
public class Orange implements Fruit {
@Override public void eat() { System.out.println("吃橘子"); } }
|
1.3 工厂类SimpleFactory
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
| package com.study.controller;
import com.study.service.Fruit; import com.study.service.Impl.Apple; import com.study.service.Impl.Orange;
public class SimpleFactory {
public static Fruit getInstance(String className){
Fruit f = null; if(className.equals("apple")){ f = new Apple(); } if(className.endsWith("orange")){ f = new Orange(); } return f; }
}
|
1.4 测试类SimpleFactoryTest
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
| package com.study.controller;
import com.study.service.Fruit; import org.junit.Test;
public class SimpleFactoryTest extends BaseTest {
@Test public void getInstance() {
Fruit apple = SimpleFactory.getInstance("apple"); apple.eat();
Fruit orange = SimpleFactory.getInstance("orange"); orange.eat(); }
}
|
二、反射+简单工厂模式
如果增加了水果,比如香蕉,那么在工厂类里面也要进行相关的修改了,这样不合理,而java的反射机制可以解决这个问题.
2.1 反射工厂类ReflexFactory
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
| package com.study.controller;
import com.study.service.Fruit;
public class ReflexFactory {
public static Fruit getInstance(String className){
Fruit f = null; try { f = (Fruit) Class.forName(className).newInstance(); } catch (Exception e) { e.printStackTrace(); } return f; }
}
|
2.2 测试类ReflexFactoryTest
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
| package com.study.controller;
import com.study.service.Fruit; import org.junit.Test;
public class ReflexFactoryTest extends BaseTest {
@Test public void getInstance() {
Fruit apple = ReflexFactory.getInstance("com.study.service.Impl.Apple"); apple.eat();
Fruit orange = ReflexFactory.getInstance("com.study.service.Impl.Orange"); orange.eat(); } }
|
三、反射+简单工厂模式+xml配置文件
3.1 实例配置类PropertiesOperate
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| package com.study.controller;
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.Properties;
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)); } catch (Exception e) { e.printStackTrace(); } }else{ this.save(); } }
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"); } catch (Exception e) { e.printStackTrace(); } } public Properties getProperties(){ return this.pro; }
}
|
3.2 测试类PropertiesOperateTest
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
| package com.study.controller;
import com.study.service.Fruit; import org.junit.Test; import java.util.Properties;
public class PropertiesOperateTest extends BaseTest {
@Test public void getProperties(){
Properties pro=new PropertiesOperate().getProperties();
Fruit apple = ReflexFactory.getInstance(pro.getProperty("apple")); apple.eat();
Fruit orange = ReflexFactory.getInstance(pro.getProperty("orange")); orange.eat();
} }
|
四、终极版本Spring IOC
以后如果要增加新的水果类,都要在这个配置文件里面登记。这时我们可以说配置文件可以控制程序的执行,现在看起来有点像spring的ioc了。下面我们来看看Spring IOC是如何实现的。
4.1 实体类Person和Grade
实体类Person:
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 35 36 37 38 39 40
| 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 28 29 30 31
| package com.study.entity;
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
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 35 36 37 38 39 40 41 42
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="Person" class="com.study.entity.Person"> <property name="name"> <value>Howe Hsiang</value> </property>
<property name="age"> <value>23</value> </property>
<property name="grade"> <ref bean = "Grade"/> </property> </bean>
<bean id="Grade" class="com.study.entity.Grade"> <property name="math"> <value>99</value> </property>
<property name="english" > <value>59</value> </property> </bean>
</beans>
|
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 35 36 37 38 39 40
| import com.study.controller.BaseTest; import com.study.entity.Grade; import com.study.entity.Person; import org.junit.Test; 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;
import java.io.File;
public class SpringIocTest extends BaseTest {
@Test public void getSpringIocInfo() {
BeanFactory factory = new ClassPathXmlApplicationContext("Bean.xml");
Person person =(Person) factory.getBean("Person"); Grade grade=(Grade)factory.getBean("Grade");
System.out.println( "姓名:"+person.getName()+ "; " + "年龄:"+person.getAge() + "; " + "数学成绩:"+grade.getMath()+ "; " + "英语成绩:"+grade.getEnglish()); }
}
|
五、其他
1、关于Spring读取配置文件的方法
applicationcontext—
FileSystemXmlApplicationContext—这个方法是从文件绝对路径加载配置文
ClassPathXmlApplicationContext—这个方法是从classpath下加载配置文件(适合于相对路径方式加载)
XmlWebApplicationContext—-专为web工程定制的方法,推荐Web项目中使用。
beanfactory—
ClassPathResource — 从系统的类路径中加载
FileSystemResource — 从文件系统加载,比如说自己指定配置文件的全路径
InputStreamResource — 从输入流中加载
ServletContextResource — 从Servlet 上下文环境中加载
UrlResource — 从指定的Url加载
2、BeanFactory和ApplicationContext的区别
ApplicationContext接口,它由BeanFactory接口派生而来,因而提供BeanFactory所有的功能。
ApplicationContext以一种更向面向框架的方式工作以及对上下文进行分层和实现继承,ApplicationContext包还提供了以下的功能:
• MessageSource, 提供国际化的消息访问
• 资源访问,如URL和文件
• 事件传播
• 载入多个(有继承关系)上下文,使得每一个上下文都专注于一个特定的层次,比如应用的web层
最主要的就是BeanFactory延迟加载,当使用到getBean的时候才会抛异常,而ApplicationContext在刚开始启动加载的时候就会抛出异常,这样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用ApplicationContext。
注: SpringIOC详解
本文标题: Spring框架详解核心IOC-开发篇
本文作者: 狂欢马克思
发布时间: 2024年06月01日 00:00
最后更新: 2025年01月03日 13:59
原始链接: https://haoxiang.eu.org/2552a56/
版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0许可协议,转载请注明出处!