Spring IoC 简单案例

Posted GoldenaArcher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring IoC 简单案例相关的知识,希望对你有一定的参考价值。

Spring IoC 简单案例

IoC(Inversion of Control)是一种设计模式,维基百科的说法是这样的:

Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式地用 new 建立 B 的对象。

采用依赖注入技术之后,A 的代码只需要定义一个 private 的B对象,不需要直接 new 来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如XML)来指定。

IoC也可以理解为把流程的控制从应用程序转移到框架之中。以前,应用程序掌握整个处理流程;现在,控制权转移到了框架,框架利用一个引擎驱动整个流程的执行,框架会以相应的形式提供一系列的扩展点,应用程序则通过定义扩展的方式实现对流程某个环节的定制,“框架Call应用”。基于MVC的web应用程序就是如此。

简单的说就是,提供一个 callback ——any kind of callback (which controls reaction) 而非直接由开发直接控制管理 ——in other words, inversion and/or redirecting control to external handler/controller

参考案例如下:

创建一个教练管理软件,这个教练管理软件需要满足两个需求:

  • 可配置
  • 可以更换为其他运动教练

使用非 IoC 的实现如下:

package springdemo;

public interface Coach 
	public String getDailyWorkout();

package springdemo;

public class TrackCoach implements Coach 

	@Override
	public String getDailyWorkout() 
		return "Run a hrad 5k.";
	


package springdemo;

public class BaseballCoach implements Coach 

	@Override
	public String getDailyWorkout() 
		return "Spend 30 minutes on batting practice.";
	

package springdemo;

public class MyApp 
	public static void main(String[] args) 
		// create the object
		Coach theCoach = new TrackCoach();
        // Coach theCoach = new BaseballCoach();
		// use the object
		System.out.println(theCoach.getDailyWorkout());
	

流程图为;

baseball coach track coach Coach App

这个实现方法中,要想要新建一个任意教练的实例都必须要在代码中进行修改,这样就无法满足一个可配置的需求。但是,这个时候可以借助 Spring IoC 来完成这一需求。

Spring 中有三种方式可以实现 IoC:

  1. XML 配置(旧)
  2. Java 注解(新)
  3. Java 代码(新)

这里会通过 XML 来完成配置。

开发过程如下:

  1. 配置 spring beans
  2. 创建 sprint container
  3. 通过 container 获取 beans

一个 “Spring Bean” 简单来说就是一个 Java 对象,官方文档中写着:

In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.

XML 配置 Spring Bean

XML 文件有自己的格式,主体部分如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Define your beans here -->
    <!-- id is like an alias -->
    <bean id="myCoach" class="springdemo.TrackCoach"></bean>
    
</beans>

这里主要的部分就是这一行:<bean id="myCoach" class="springdemo.TrackCoach"></bean>,这一行就创建了一个新的 Spring Bean,指向的类为 TrackCoach,之后也可以修改为 TrackCoach 或是其他,但是无论如何都不需要修改 Java 源码。

这时候创建一个新的主函数导入 XML 文件:

package springdemo;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloSpringApp 
	public static void main(String[] args) 
		// load the spring configuration file
		ClassPathXmlApplicationContext context = 
				new ClassPathXmlApplicationContext("applicationContext.xml");
		
		// retrieve bean from spring container
		// 2nd arg is the interface
		Coach theCoach = context.getBean("myCoach", Coach.class);
		
		// call methods on the bean
		System.out.println(theCoach.getDailyWorkout());
		
		// close the context
		context.close();
	

这样在修改教练的时候不需要修改源码,只需要修改配置文件 applicationContext.xml 即可。

额外的 logging

Spring 5.1 默认移除了一部分的 Logging,这里的配置会把一些 logging 加回来:

新的 Logging java:

package springdemo;

import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
 
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyLoggerConfig 
	private String rootLoggerLevel;
	private String printedLoggerLevel;
	
	public void setRootLoggerLevel(String rootLoggerLevel) 
		this.rootLoggerLevel = rootLoggerLevel;
	
 
	public void setPrintedLoggerLevel(String printedLoggerLevel) 
		this.printedLoggerLevel = printedLoggerLevel;
	
 
	public void initLogger() 
 
		// parse levels
		Level rootLevel = Level.parse(rootLoggerLevel);
		Level printedLevel = Level.parse(printedLoggerLevel);
		
		// get logger for app context
		Logger applicationContextLogger = Logger.getLogger(AnnotationConfigApplicationContext.class.getName());
 
		// get parent logger
		Logger loggerParent = applicationContextLogger.getParent();
 
		// set root logging level
		loggerParent.setLevel(rootLevel);
		
		// set up console handler
		ConsoleHandler consoleHandler = new ConsoleHandler();
		consoleHandler.setLevel(printedLevel);
		consoleHandler.setFormatter(new SimpleFormatter());
		
		// add handler to the logger
		loggerParent.addHandler(consoleHandler);
	

XML 配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Define your beans here -->
    <!-- id is like an alias -->
    <bean id="myCoach" class="springdemo.TrackCoach"></bean>
    
    <bean id="myLoggerConfig" class="springdemo.MyLoggerConfig" init-method="initLogger">
    	<property name="rootLoggerLevel" value="FINE" />
    	<property name="printedLoggerLevel" value="FINE"/>
    </bean>
    
</beans>

Reference

以上是关于Spring IoC 简单案例的主要内容,如果未能解决你的问题,请参考以下文章

Spring 框架基础(03):核心思想 IOC 说明,案例演示

Spring IoC 简单案例

Spring IoC 简单案例

Spring入门案例(简单)

Spring 控制反转

Spring的学习_____2.IoC 控制反转