前面我们说了简单的实例化Bean(Spring IOC),没有涉及Bean之间的关系,下面我们来说一下配置Bean之间的关系,即依赖注入(DI)。
Spring IoC容器的依赖有两层含义:Bean依赖容器和容器注入Bean的依赖资源
Bean依赖容器,就是说Bean要依赖于容器,这里的依赖是指容器负责创建Bean并管理Bean的生命周期,正是由于由容器来控制创建Bean并注入依赖,也就是控制权被反转了,此处的依赖是指Bean和容器之间的依赖关系。
容器注入Bean的依赖资源容器负责注入Bean的依赖资源,依赖资源可以是Bean、外部文件、常量数据等,在Java中都反映为对象,并且由容器负责组装Bean之间的依赖关系,此处的依赖是指Bean之间的依赖关系,可以认为是传统类与类之间的“关联”、“聚合”、“组合”关系。
依赖注入意义:
1、 动态替换Bean依赖对象,程序更加灵活;
2、 更好实践面向接口编程,代码更清晰:在Bean中只需指定依赖对象的接口,接口定义依赖对象完成的功能,通过容器注入依赖实现;
3、 更好实践优先使用对象组合,而不是类继承:因为IoC容器采用注入依赖,也就是组合对象,从而更好的实践对象组合。
采用对象组合,Bean的功能可能由几个依赖Bean的功能组合而成,其Bean本身可能只提供少许功能或根本无任何功能,全部委托给依赖Bean,对象组合具有动态性,能更方便的替换掉依赖Bean,从而改变Bean功能。而如果采用类继承,Bean没有依赖Bean,而是采用继承方式添加新功能,,而且功能是在编译时就确定了,不具有动态性,而且采用类继承导致Bean与子Bean之间高度耦合,难以复用。
4、 增加Bean可复用性。
5、 降低Bean之间耦合。
6、 代码结构更加清晰。
从上面看可以发现,依赖注入只是一种装配对象的手段,如何设计好类的结构才是王道。
前面我们了解了Bean依赖IoC容器,今天开始理一下IoC如何注入Bean的依赖资源,其实现方式主要有以下几种:
1、 构造器注入,就是容器实例化Bean时注入那些依赖,通过在在Bean定义中指定构造器参数进行注入依赖,包括实例工厂方法参数注入依赖,但静态工厂方法参数不允许注入依赖。
2、 Setter注入,通过setter方法进行注入依赖。
3、 方法注入,能通过配置方式替换掉Bean方法,也就是通过配置改变Bean方法功能。
构造器注入
构造函数
public class HelloDIImpl implements HelloDI { private String message; private int index; public HelloDIImpl(String message, int index) { this.message = message; this.index = index; } @Override public void sayHello() { System.out.println(index + ":" + message); } }
静态工厂类
public static HelloDIImpl newInstance(String message, int index) { return new HelloDIImpl(message, index); }
实例工厂类
public HelloDIImpl newInstance(String message, int index) { return new HelloDIImpl(message, index); }
<!-- 通过构造器参数索引方式依赖注入 --> <bean id="byIndex" class="com.iflytek.demo.HelloDIImpl"> <constructor-arg index="0" value="Hello byIndex" /> <constructor-arg index="1" value="1" /> </bean> <!-- 通过构造器参数类型方式依赖注入 --> <bean id="byType" class="com.iflytek.demo.HelloDIImpl"> <constructor-arg type="java.lang.String" value="Hello byType" /> <constructor-arg type="int" value="2" /> </bean> <!-- 通过构造器参数名称方式依赖注入 --> <bean id="byName" class="com.iflytek.demo.HelloDIImpl"> <constructor-arg name="message" value="Hello byName" /> <constructor-arg name="index" value="3" /> </bean>
Setter注入
Setter注入(根据setter名字进行注入),是通过在通过构造器实例化好Bean后,通过调用Bean类的setter方法进行注入依赖。
public class HelloDIImpl02 implements HelloDI { private String message; private int index; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } @Override public void sayHello() { System.out.println(index + ":" + message); } }
可以没有getter方法,但是完整的类还写上比较好。
<!-- 通过setter方式进行依赖注入 --> <bean id="bySetter" class="com.iflytek.demo.HelloDIImpl02"> <property name="message" value="Hello bySetter" /> <property name="index"> <value>1</value> </property> </bean>
注入常量
<property name="message" value="Hello World!"/>
注入Bean ID
用于注入Bean的ID,ID是一个常量不是引用,且类似于注入常量,但提供了错误验证功能
<bean id="bean1" class="java.lang.String"> <constructor-arg index="0" value="test"/> </bean> <bean id="bean2" class="java.lang.String"> <constructor-arg index="0" value="test"/> </bean> <bean id="ByIdrefBean" class="com.iflytek.demo.IdZR"> <property name="id"><idref bean="bean1"/></property> </bean> <bean id="ByIdrefLocal" class="com.iflytek.demo.IdZR"> <property name="id"><idref local="bean2"/></property> </bean>
从配置中可以看出,注入的Bean的ID是一个java.lang.String类型,即字符串类型,因此注入的同样是常量,只是具有校验功能。
<idref bean="……"/>将在容器初始化时校验注入的ID对于的Bean是否存在,如果不存在将抛出异常。
<idref local="……"/>将在XML解析时校验注入的ID对于的Bean在当前配置文件中是否存在,如果不存在将抛出异常,它不同于<idref bean="……"/>是校验发生在XML解析式而非容器初始化时,且只检查当前配置文件中是否存在相应的Bean,可能会发生不可预料的错误。因此如果想注入Bean的ID,推荐使用bean的方式。
注入集合
1、List
public class ListDemo { private List<String> values; public List<String> getValues() { return values; } public void setValues(List<String> values) { this.values = values; } }
<bean id="byListBean" class="com.iflytek.demo.ListDemo"> <property name="values"> <list value-type="java.lang.String" merge="default"> <value>1</value> <value>2</value> <value>3</value> </list> </property> </bean>
2、Set则将上面的List替换成Set即可。
3、数组
public class ArrayDemo { private String[] array; private String[][] array2; //getter setter }
<bean id="byArray" class="com.iflytek.demo.ArrayDemo"> <property name="array"> <array value-type="java.lang.String" merge="default"> <value>1</value> <value>2</value> <value>3</value> </array> </property> <property name="array2"> <array> <array> <value>1</value> <value>2</value> <value>3</value> </array> <array> <value>4</value> <value>5</value> <value>6</value> </array> </array> </property> </bean>
4、Map
<bean id="byMap" class="com.iflytek.demo.MapDemo"> <property name="values"> <map key-type="java.lang.String" value-type="java.lang.String"> <entry> <key><value>1</value></key> <value>11</value> </entry> <entry key="2" value="22"/> </map> </property> </bean>
5、Properties注入
package com.iflytek.demo import java.util.Properties; public class PropertiesDemo { private Properties values; public Properties getValues() { return values; } public void setValues(Properties values) { this.values = values; } }
<bean id="byProperties1" class="com.iflytek.demo.PropertiesDemo"> <property name="values"> <props value-type="int" merge="default"> <prop key="1">12sw</prop> <prop key="2">2</prop> </props> </property> </bean> <bean id="byProperties2" class="com.iflytek.demo.PropertiesDemo"> <property name="values"> <value> 1=11 2=22, 3=33; 4=44 </value> </property> </bean>
引用其他Bean
引用其他Bean的步骤与注入常量的步骤一样,可以通过构造器注入及setter注入引用其他Bean,只是引用其他Bean的注入配置稍微变化了一下:可以将“<constructor-arg index="0" value="Hello World!"/>”和“<property name="message" value="Hello World!"/>”中的value属性替换成bean属性,其中bean属性指定配置文件中的其他Bean的id或别名。另一种是把<value>标签替换为<.ref bean=”beanName”>,bean属性也是指定配置文件中的其他Bean的id或别名。
构造器注入方式:
通过” <constructor-arg>”标签的ref属性来引用其他Bean,这是最简化的配置:
通过” <constructor-arg>”标签的子<ref>标签来引用其他Bean,使用bean属性来指定引用的Bean:
setter注入方式:
通过” <property>”标签的ref属性来引用其他Bean,这是最简化的配置:
通过” <property>”标签的子<ref>标签来引用其他Bean,使用bean属性来指定引用的Bean:
public class HelloDIDecorator implements HelloDI { private HelloDI helloDi; // 空参构造器 public HelloDIDecorator() { } // 有参构造器 public HelloDIDecorator(HelloDI helloDi) { this.helloDi = helloDi; } public void setHelloDi(HelloDI helloDi) { this.helloDi = helloDi; } @Override public void sayHello() { System.out.println("====================="); helloDi.sayHello(); System.out.println("====================="); } }
<!-- 定义依赖Bean --> <bean id="helloDIImpl" class="com.iflytek.demo.HelloDIImpl" /> <!-- 通过构造器注入 --> <bean id="byConstructor" class="com.iflytek.demo.HelloDIDecorator"> <constructor-arg index="0" ref="helloDIImpl" /> </bean> <!-- 通过构造器注入 --> <bean id="bySetter" class="com.iflytek.demo.HelloDIDecorator"> <property name="helloDi"> <ref bean="helloDIImpl" /> </property> </bean>
内部Bean定义
<bean id="byInner" class="com.iflytek.demo.HelloDIDecorator"> <property name="helloDi"> <bean id="helloDIImpl" class="com.iflytek.demo.HelloDIImpl" /> </property> </bean>
处理null值
转自:http://jinnianshilongnian.iteye.com/
相关推荐
本文将详细介绍 Java 中的依赖注入(Dependency Injection,简称 DI),特别是 setter 注入和构造器注入两种方式的使用和实现。 一、DI 依赖注入 依赖注入是指在容器中建立 Bean 与 Bean 之间的依赖关系的过程。...
在Spring框架的学习中,依赖注入(Dependency Injection,简称DI)是一个核心概念,它极大地提高了代码的可测试性和可维护性。本篇笔记将探讨Spring如何实现依赖注入,并通过实例进行详细解析。 首先,理解依赖注入...
下面我们将深入探讨Spring依赖注入的概念、工作原理以及如何在实践中应用。 1. **依赖注入概念**: - 依赖:一个类对另一个类的使用称为依赖。 - 注入:将依赖的对象传递给需要它的类,而不是由类自己去创建或...
Spring框架则是一个全面的企业级应用开发框架,它提供了依赖注入(DI)和面向切面编程(AOP)等功能,简化了Java应用的开发。Spring也提供了一个强大的事务管理器,可以管理数据库事务。 在Mybatis与Spring的整合中...
标题中的"Spring的IOC和DI的区别"涉及到Spring框架的核心特性,即控制反转(Inversion of Control,简称IOC)和依赖注入(Dependency Injection,简称DI)。这两个概念是理解Spring框架工作方式的关键。 首先,控制...
本项目以"Spring_依赖注入_面向接口编程_不同加载方式"为主题,旨在帮助初学者理解Spring的核心特性——依赖注入(Dependency Injection,简称DI),以及如何通过面向接口编程来提高代码的可维护性和可扩展性。...
在Spring框架中,依赖注入(Dependency Injection,DI)是一种核心特性,它允许开发者将对象的创建和组装过程从代码中分离出来,提高了代码的可测试性和可维护性。Spring提供了多种注解来实现依赖注入,包括@...
在`chapter8`这个文件夹中,可能包含了关于Spring依赖注入的深入讲解,包括如何配置和使用,以及在实际项目中的应用示例。学习这部分内容可以帮助你理解如何利用Spring的DI特性来构建更优雅、更易于维护的Java应用。...
本篇学习笔记将深入剖析Spring依赖注入的原理,通过源码分析帮助我们理解这一核心机制。 首先,依赖注入允许我们解耦组件之间的关系,使得各个组件可以独立地进行开发、测试和维护。在Spring中,DI主要通过两种方式...
3. **MapperScannerConfigurer**:这个类用于扫描指定包下的 Mapper 接口,并自动将其注册到 Spring 容器中,这样就可以通过依赖注入的方式直接使用这些接口。 4. **MapperFactoryBean**:它是 Spring 的 ...
集成Netty和Spring MVC的关键在于将Spring的依赖注入(DI)特性引入到Netty的生命周期中。这通常可以通过实现Spring的ApplicationContextAware接口来实现,这样可以在Netty的启动过程中获取到Spring的...
Spring框架是Java开发中不可或缺的一部分,它以其强大的依赖注入(DI)和面向切面编程(AOP)功能闻名。在Spring开发中,依赖包和配置文件是构建应用程序的基础。本篇将详细介绍Spring依赖包和配置文件的相关知识。 ...
依赖注入(DI)是Spring框架的核心特性之一,它允许我们把对象的依赖关系从代码中解耦出来,转而由Spring容器来管理。在传统的编程模式中,对象通常自行创建和管理它们所依赖的对象,但在Spring中,这些依赖是由外部...
【Spring】是Java领域中广泛使用的轻量级框架,它提供了依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)等核心功能。依赖注入允许开发者在运行时通过配置文件或注解来管理...
这个整合包使得在Spring应用中使用MyBatis变得更加简单,无需手动配置SqlSessionFactory或SqlSessionTemplate,而是通过Spring的依赖注入来管理和使用MyBatis的数据访问组件。 1. MyBatis-Spring整合的核心概念: ...
2. **依赖注入**:在转账案例中,Spring通过DI管理对象之间的依赖关系,使得代码更加灵活和可测试。开发者可以声明所依赖的组件,由Spring容器负责实例化、装配以及管理这些组件。 3. **Spring事务管理**:转账操作...
标题 "03_mvc和依赖注入部分实现_源码" 暗示了这是一个关于Java Web开发中的关键概念——Model-View-Controller(MVC)架构以及依赖注入(Dependency Injection,DI)技术的实践项目。在Java开发中,MVC模式被广泛...
在Spring框架中,依赖注入(Dependency Injection,简称DI)是一种重要的设计模式,它使得对象之间的耦合度降低,提高了代码的可测试性和可维护性。本文将深入探讨Spring中的依赖注入实现方式,以及如何通过样例文件...
首先,Spring框架是整个SSM的核心,它提供依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)等核心功能。依赖注入使得对象之间的依赖关系不再硬编码,而是通过配置来决定,...
在Java Web开发中,这两个框架经常一起使用,Spring 提供了依赖注入(DI)和面向切面编程(AOP)等功能,而 Struts 2 则是一个强大的MVC(Model-View-Controller)框架,负责处理用户请求和业务逻辑。 Struts 2 和 ...