1. 程式人生 > >Spring IOC的元件註冊、依賴注入的實現方式

Spring IOC的元件註冊、依賴注入的實現方式

IOC—Inversion of Control,控制反轉,是一種設計思想它能指導程式設計師如何設計出鬆耦合、更優良的程式程式碼。

如果不用IOC,建立、銷燬物件、物件之間的依賴關係,都需要程式設計師自己在程式碼裡面體現,各種new。

而有了IOC容器後,程式碼裡只需要定義物件的基本資訊,並將它註冊到IOC容器中,讓IOC管理它的生命週期(建立和銷燬)以及它們之間的依賴關係。

第一章:將元件(物件)新增到ioc容器的四種方式

        第一節:bean方式(註解和xml兩種方式)

        第二節:bean工廠方式(靜態工廠、例項化工廠兩種)

        第三節:包掃描

[email protected]、@Service、@Repository@Component(註解和xml兩種方式)

        第四節:@Import註解快速註冊

        第五節(拓展):@Conditional 根據條件判斷bean是否可以新增到容器中,Spring底層經常使用

        第六節(拓展):@profile 根據當前環境,動態的啟用和切換一系列元件

第二章:自動裝配實現方式(即DI 依賴注入實現屬性賦值)

         第七節:@Autowired 自動裝配

         第八節:JSR-250(java規範)的註解@Resource

         第九節:xml配置實現裝配的多種方式

         第十節(拓展):自定義元件實現xxxAware介面,使用spring底層的一些元件(BeanFactory、ApplictionContext等)

Action one:建立maven專案,新增spring和junit依賴:

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>4.3.12.RELEASE</version>
</dependency>

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.12</version>
	<scope>test</scope>
</dependency>

第一節:bean方式註冊元件

>定義User物件

public class User {
	public User() {
		super();
	}
	public User(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	private String name;
	private Integer age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
}

>xml方式實現註冊

<bean id="user" class="com.mote.pojo.User">
     <property name="name" value="zhangsan"></property>
     <property name="age" value="22"></property>
</bean>

>註解方式實現註冊

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.mote.pojo.User;

//@Configuration 標註這是一個註解配置類,該類就相當於spring的配置檔案applictionContext.xml
@Configuration 
public class MainConfig {
	/**
	 * @Bean表示向IOC容器中註冊bean,value指定bean名稱,如果不指定,預設使用方法名
	 */
	@Bean(value="user")
	public User user(){
		return new User("lisi",25);
	}
}

>測試類

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mote.config.MainConfig;
import com.mote.pojo.User;

public class MainTest {
	
	@Test //註解測試
	public void testAnnotation(){
		
		//載入Spring註解配置類
		AnnotationConfigApplicationContext application = new AnnotationConfigApplicationContext(MainConfig.class);
		//從容器中獲取bean
		User user = application.getBean(User.class);
		System.out.println(user);
	}
	
	@Test //xml測試
	public void testXml(){
		//載入Spring-xml配置檔案
		ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("beans.xml");
	    //從容器中獲取bean
		User user = application.getBean(User.class);
		System.out.println(user);
	}
}

>列印結果:

第二節:bean工廠方式(靜態工廠、例項化工廠兩種)

1:靜態工廠模式:工廠類本身不需要例項化, 通過工廠類直接呼叫其中的靜態方法生成bean物件。

定義物件Car:

public class Car {
	private String name;
	private double money;
	public Car() {
		super();
	}
	public Car(String name, double money) {
		super();
		this.name = name;
		this.money = money;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getMoney() {
		return money;
	}
	public void setMoney(double money) {
		this.money = money;
	}
	@Override
	public String toString() {
		return "Car [name=" + name + ", money=" + money + "]";
	}
	
}

定義生產Car的靜態工廠:

public class CarFactory {
	/**
	 * 靜態方法,返回Car例項
	 * @return
	 */
	public static Car getCar(){
		return new Car("寶馬",10000000.00);
	}

}

配置xml:

<!-- 配置Car工廠,呼叫getCar(),返回Car例項 -->
<bean id="car" class="com.mote.pojo.CarFactory" factory-method="getCar"></bean>

測試列印:

public class MainTest {
	@Test //註解測試
	public void testAnnotation(){
		ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("beans.xml");
		Car car = application.getBean(Car.class);
		//Car car1 = (Car) application.getBean("car");
		System.out.println(car);
	}
}

2:例項工廠模式:因為getCar方法不是靜態的,需要先例項化CarFactory工廠,在通過carFactory呼叫getCar生產bean物件

定義物件Car:(和靜態工廠模式的測試一致)

定義Car的例項化工廠:

public class CarFactory {
	
	public Car getCar(){
		return Car("寶馬",10000000.00);
	}

}

配置xml:

<!-- 配置Car工廠-->
<bean id="carFactory" class="com.mote.pojo.CarFactory"></bean>

<!-- 呼叫carFactory的getCar,配置car的例項  -->
<bean id="car" factory-bean="carFactory" factory-method="getCar"></bean>

測試列印:(和靜態工廠模式的測試一致)

第三節:包掃描[email protected]、@Service、@Repository@Component(註解和xml兩種方式)

>定義UserController,UserService,UserDao,UserTest,分別加上述註解

>專案目錄結構:

>xml方式實現包掃描註冊

<!-- 開啟包掃描 ,指定的包以及子包下 只要標註了@Controller、@Service、@Repositoy、@Component
     的類都會被新增到spring容器中-->
<context:component-scan base-package="com.mote"/>

>註解方式實現包掃描註冊

@Configuration
//@ComponentScan 開啟包掃描,value指定包名
@ComponentScan(value = "com.mote")
public class MainConfig {
	
}

>測試類

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mote.config.MainConfig;

public class MainTest {
	@Test //註解測試
	public void testAnnotation(){
		//載入Spring註解配置類
		AnnotationConfigApplicationContext application = new AnnotationConfigApplicationContext(MainConfig.class);
		
		//獲取註冊到容器中的元件name集合,遍歷列印
		String[] names = application.getBeanDefinitionNames();
		for (String name : names) {
			System.out.println(name);
		}
	}
	
	@Test //xml測試
	public void testXml(){
		//載入Spring-xml配置檔案
		ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("beans.xml");
		
		String[] names = application.getBeanDefinitionNames();
		for (String name : names) {
			System.out.println(name);
		}
	}
}

>列印結果

第四節:@Import註解快速註冊

Import註解實現註冊有三種實現方式

1:@Import(要新增的元件)

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import com.mote.dao.UserDao;
import com.mote.service.UserService;

@Configuration
//@Import 快速給容器中匯入一個元件,預設id是全類名
//@Import(UserController.class)     //註冊一個
@Import({UserService.class,UserDao.class})   //註冊多個
public class MainConfig {
	
}

2:實現ImportSelector介面,自定義返回要註冊的元件

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class MyImport implements ImportSelector {

	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		return new String[] { "com.mote.controller.UserService","com.mote.dao.UserDao" };
	}

}
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(MyImport.class)
public class MainConfig {
	
}

3:實現ImportBeanDefinitionRegistrar介面,實現手動註冊

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import com.mote.dao.UserDao;

public class MyImport implements ImportBeanDefinitionRegistrar {

	/**
	 * AnnotationMetadata:當前類的註解資訊
	 * BeanDefinitionRegistry:BeanDefinition註冊類
	 */
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata,
			BeanDefinitionRegistry registry) {
		//判斷容器中是否註冊userDao
		boolean flag = registry.containsBeanDefinition("userDao");
		
		//向容器中註冊bean,並指定bean_name為userDao
		BeanDefinition beanDefinition = new RootBeanDefinition(UserDao.class);
		registry.registerBeanDefinition("userDao", beanDefinition );
	}

}
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(MyImport.class)
public class MainConfig {
	
}

>測試類

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.mote.config.MainConfig;

public class MainTest {
	@Test //註解測試
	public void testAnnotation(){
		//載入Spring註解配置類
		AnnotationConfigApplicationContext application = new AnnotationConfigApplicationContext(MainConfig.class);
		
		//獲取註冊到容器中的元件name集合,遍歷列印
		String[] names = application.getBeanDefinitionNames();
		for (String name : names) {
			System.out.println(name);
		}
	}
}

>列印結果

方式一:

方式二:

方式三:

第五節(拓展):@Conditional 根據條件判斷bean是否可以新增到容器中,Spring底層經常使用

需求描述:如果當前系統是Windows,註冊User(“bier”,30),反之不註冊

1:實現Condition介面,書寫判斷邏輯

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class MyConditional implements Condition{
	/**
	 * ConditionContext:判斷條件使用的上下文
	 * AnnotatedTypeMetadata:註釋資訊
	 */
	public boolean matches(ConditionContext context,
			AnnotatedTypeMetadata metadata) {
		//獲取當前執行環境資訊
		Environment environment = context.getEnvironment();
		//獲取當前系統型別,判斷是否是Windows
		String type = environment.getProperty("os.name");
	    return type.contains("Windows")?true:false;

	}

}

2:使用@Conditional註解進行判斷

import com.mote.pojo.User;

@Configuration
public class MainConfig {
	
	@Bean
	@Conditional({MyConditional.class})
	public User bier(){
		return new User("bier",30);
	}
	
}

小技巧:eclipse模擬linux環境

測試類中點選滑鼠右鍵,Run AS  >   RunConfigurations

測試:

public class MainTest {
	@Test //註解測試
	public void test(){
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        String[] names = context.getBeanDefinitionNames(); //列印spring容器註冊的bean名稱
        for (String name : names) {
			System.out.println(name);
		}
	}
}

windows環境執行結果列印:

linux系統執行結果列印:

 第六節(拓展):@profile 根據當前環境,動態的啟用和切換一系列元件

 案例功能描述:根據當前環境決定使用相應的資料庫
 * 預設情況下:資料庫A
 * 測試環境下:資料庫B
 * 開發環境下:資料庫C

匯入maven:dhcp連線池和mysql驅動

<dependency>
	<groupId>commons-dbcp</groupId>
	<artifactId>commons-dbcp</artifactId>
	<version>1.4</version>
</dependency>

<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>6.0.6</version>
</dependency>

案例程式碼:

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

/**
 * @Profile:加了該環境標識的bean,只有這個環境被啟用後後才能註冊到容器
 */
@Configuration
public class MainConfig {
	
	@Bean
	@Profile("default")   //不指定的情況下,預設使用的資料庫
	public BasicDataSource dataSourceDefault() {
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setUrl("jdbc:mysql://localhost:3306/A");
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUsername("root");
		dataSource.setPassword("123456");
		return dataSource;
	}

	@Bean
	@Profile("test")   //測試環境
	public BasicDataSource dataSourceTest() {
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setUrl("jdbc:mysql://localhost:3306/B");
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUsername("root");
		dataSource.setPassword("123456");
		return dataSource;
	}
	
	@Bean
	@Profile("devlop")   //開發環境
	public BasicDataSource dataSourceDev() {
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setUrl("jdbc:mysql://localhost:3306/C");
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUsername("root");
		dataSource.setPassword("123456");
		return dataSource;
	}
	
}

測試程式碼:

public class MainTest {
	@Test //註解測試
	public void test(){
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
		String[] names = context.getBeanDefinitionNames();
		for (String name : names) {
			System.out.println(name);
		}
	}
}

測試一:不指定環境變數,直接執行,列印如下

測試二:指定環境為test,執行列印

列印結果:

  第七節:@Autowired 自動裝配

                @Autowired使用前提,userService已經註冊到spring容器中

@Autowired實現裝配的三種操作方式

1)標註在屬性上

/**
	 * @Autowired 首先根據UserService型別去容器尋找Bean,
	 * 如果這個型別有多個Bean,比如userService/userService1
	 * 那麼@Autowired就會根據屬性名稱userService去匹配.
	 * 
	 * 另外,可以使用註解@Qualifier配合@Autowired使用,用於指定容器中特定id的Bean
	 */
	//@Qualifier("userService")
	@Autowired
	private UserService userService;

2)標註在set方法上

private UserService userService;

@Autowired
public void setUserService(UserService userService) {
	this.userService = userService;
}

3)標註在構造器上

private UserService userService;
	
/**
* 如果該類只有這一個構造器,那麼這個@Autowired註解可以省略不寫
* 因為spring容器生成的時候,就必須根據這個構造器去建立物件
*/
@Autowired
public UserController(UserService userService) {
	super();
	this.userService = userService;
}

 第八節:JSR-250(java規範)的註解@Resource

@Resource使用前提,userService已經註冊到spring容器中  

/**
* @Resource JSR-250註解,用來啟用資源,通過name屬性,指定容器中特定id的bean
*/
@Resource(name="userService")
private UserService userService;

第九節:xml配置實現裝配的多種方式

1)set方法注入依賴

xml:

<bean id="userService" class="com.mote.service.UserService"/>
     
<bean class="com.mote.controller.UserController">
   <property name="userService" ref="userService"/>
</bean>

程式碼:

private UserService userService;

public void setUserService(UserService userService) {
	this.userService = userService;
}

2)構造器注入依賴

xml:

<bean id="userService" class="com.mote.service.UserService"></bean>

<bean class="com.mote.controller.UserController">
     <constructor-arg name="userService" ref="userService"></constructor-arg>
</bean>

程式碼:

private UserService userService;
	
public UserController(UserService userService) {
	this.userService = userService;
}

3)靜態工廠注入依賴和例項化工廠注入依賴

這兩種方式其實就是通過set方法注入依賴,只是向容器中新增bean的方式不同。

第十節(拓展):自定義元件實現xxxAware介面,使用spring底層的一些元件

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class MyAware implements ApplicationContextAware,BeanFactoryAware {

	private ApplicationContext applicationContext; //設定成員變數

	private BeanFactory beanFactory;  //設定成員變數
	
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext; //賦值
	}

	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		this.beanFactory = beanFactory;  //賦值
		
	}
	
	public void test(){
		//使用 applicationContext、beanFactory
		
	}
}

相關推薦

Spring IOC元件註冊依賴注入實現方式

IOC—Inversion of Control,控制反轉,它是一種設計思想,它能指導程式設計師如何設計出鬆耦合、更優良的程式程式碼。 如果不用IOC,建立、銷燬物件、物件之間的依賴關係,都需要程式設計師自己在程式碼裡面體現,各種new。 而有了IOC容器後,程式碼裡只需

使用XPath解析xml實現簡單的Spring IOC完成bean的依賴注入

幾天使用Xpath解析xml檔案,例項化bean,完成spring IOC bean的依賴注入的簡單實現。 假設用如下格式的bean檔案: <?xml version="1.0" encoding="UTF-8"?> <beans> <b

深入研究Spring-IoC:原始碼分析依賴注入

1.前言 對於容器建立的過程已經闡述過一遍了,下面是依賴注入的問題。Spring提供的依賴注入的方法主要由兩種:一種是通過getBean的方法;另一種是通過註解@Autowaire。 需要指出的是依賴注入的過程是使用者第一次向ioc容器索要Bean的時候開始生產的,也可以通過設定

深入淺出spring IOC中三種依賴注入方式

首先:第一個問題,參與者都有誰?1)物件2)IOC/DI容器3)某個物件的外部資源第二問題:依賴,誰依賴誰?為什麼需要依賴?依賴嘛,很好理解的,物件依賴於IOC/DI容器,至於為什麼要依賴呢?物件需要IOC/DI容器來提供物件需要的外部資源。第三個問題:注入,誰注入誰?又注入了什麼呢?顯而易見是IOC/DI容

spring IOC中三種依賴注入方式 經典總結

首先:第一個問題,參與者都有誰?1)物件2)IOC/DI容器3)某個物件的外部資源第二問題:依賴,誰依賴誰?為什麼需要依賴?依賴嘛,很好理解的,物件依賴於IOC/DI容器,至於為什麼要依賴呢?物件需要IOC/DI容器來提供物件需要的外部資源。第三個問題:注入,誰注入誰?又注入了什麼呢?顯而易見是IOC/DI容

spring IOC(控制翻轉) DI(依賴注入)AOP(面向切面)理解

 (1) 控制反轉(Inversion of Confrol):  物件的建立交給外部容器完成,這個就叫做控制反轉,  Ioc—Inversion of Control,即“控制反轉”,不是什麼技術,而是一種設計思想。在Java開發中,Ioc意味著將你設計好的物件交給容器控

Spring IoC是如何進行依賴注入

## 依賴注入(DI) **DI(Dependency Injection)**,Spring IoC 不是一種技術,而是一種思想,通過這種思想,能夠指導我們設計出鬆耦合的程式程式碼。而Spring IoC這個思想的作用體現在兩個方面,一是如何將Bean裝配到容器中去以及如何從容器中獲取Bean,二是如何解

Spring系列教程五: 依賴注入方式詳解

依賴注入的概念 Spring中的依賴注入,稱為dependency Injection,Ioc的作用降低程式之間的耦合,依賴關

Spring IOC/BeanFactory/ApplicationContext的工作流程/實現原理/初始化/依賴注入原始碼詳解

Spring的工作流程/實現原理之基石IOC/BeanFactory/ApplicationContext 更新1:2017/11/23更新2:2018/1/30(截圖)一、什麼是IOC容器?IOC(Inversion of Control)、控制反轉亦稱依賴注入.IOC容器

控制反轉IOC依賴注入方式 【調侃】IOC前世今生 IoC模式 談談對Spring IOC的理解 一個簡單的小程式演示Unity的三種依賴注入方式 小菜學習設計模式(五)—控制反轉(IocIoC模式(依賴、依賴倒置、依賴注入、控制反轉) IoC模式

轉自:https://www.cnblogs.com/ysyn/p/5563256.html 引言:    專案中遇到關於IOC的一些內容,因為和正常的邏輯程式碼比較起來,IOC有點反常。因此本文記錄IOC的一些基礎知識,並附有相應的簡單例項,而在實際專案中再複雜的應用也只是在

Spring入口_Bean的註冊依賴注入

一、Spring入口                        

Spring 依賴注入實現原理--java反射和ASM框架

依賴注入是spring的一個特性,從配置層面解決了程式耦合、依賴問題,spring提供了建構函式依賴注入、Setter方法依賴注入、自動裝配依賴注入和@autowired註解依賴注入等多種實現方式。 那麼依賴注入是如何實現的?第一反應就是java反射唄,比如建構

3.SpringIoC-基於XML的依賴注入(DI)

Bean例項在呼叫無參構造器建立了空值物件後,就要對Bean物件的屬性進行初始化。初始化是由容器自動完成的,成為注入。根據注入方式的不同,常用的有兩類:設值注入、構造注入。 還有一種實現特定介面的注入。由於採用侵入式程式設計,汙染程式碼,所以幾乎不用 記住:

(一)Spring IoC原始碼-3.其他特性的實現原理-02迴圈依賴的解決

引言:迴圈依賴就是N個類中迴圈巢狀引用,如果在日常開發中我們用new 物件的方式發生這種迴圈依賴的話程式會在執行時一直迴圈呼叫,直至記憶體溢位報錯。下面說一下Spring是如果解決迴圈依賴的。 第一種:構造器引數迴圈依賴 Spring容器會將每一個正

Spring 使用註解完成bean例項化依賴注入的相關配置以及注意事項

一、 相關配置例項化註解介紹 首先使用註解完成spring容器例項的配置,主要用到以下幾個: 1、@Repository(“name”):配置持久層例項bean,通常用在DAO; 這裡配置的name屬性相當於在 2、@Servic

巧妙運用spring依賴注入實現簡單工廠模式

舉一個業務場景:  假設有一個統一買票旅遊的入口,買完票會有一個欄位表明種類。  這些種類表明你去哪,怎麼去。  是坐飛機去奧地利,或是走路到隔壁龍蝦店,都不得而知,而且程式碼邏輯幾乎沒有關聯。這個時候我們難道要這樣寫程式碼嗎?  if(type == 1){        

Spring筆記之七(Types of Injection) Spring的三種依賴注入實現型別

本文研究Spring的三種依賴注入實現型別——介面注入(Interface Injection)、設值注入(Setter Injection)、構造子注入(Constructor Injection)。 Type1 介面注入: 傳統的建立介面物件的方法, 藉助介面來將呼叫者與

spring依賴注入方式實現(2)

依賴注入的方式1、屬性注入2、構造器注入3、工廠方法注入(很少使用,不推薦)1、屬性注入(1)屬性注入即通過 setter 方法注入Bean 的屬性值或依賴的物件(2)屬性注入使用 <proper

依賴倒置原則(DIP)控制反轉(IoC依賴注入(DI)(C#)

理解: 依賴倒置原則(DIP)主程式要依賴於抽象介面,不要依賴於具體實現。高層模組不應該依賴底層模組,兩個都應該以來抽象。抽象不應該依賴細節,細節應該依賴抽象。(具體看我上一篇貼子) 依賴倒置原則是六大設計原則中的一種,它的大致意思是所有模組都應該依賴於抽象,而不是直接依賴於另一個模組。依賴倒置原則僅僅只是一

.NET IoC模式依賴反轉(DIP)控制反轉(Ioc)依賴注入(DI)

# 依賴倒置原則(DIP) 依賴倒置(Dependency Inversion Principle,縮寫DIP)是面向物件六大基本原則之一。他是指一種特定的的解耦形式,使得高層次的模組不依賴低層次的模組的實現細節,依賴關係被顛倒(反轉),從而使得低層次模組依賴於高層次模組的需求抽象. 該原則規定: -