学习spring容器IOC(3)之依赖和依赖注入

学习开涛跟我学spring3

http://jinnianshilongnian.iteye.com/

为什么要应用依赖注入,应用依赖注入能给我们带来哪些好处呢?

1.动态替换Bean依赖对象,程序更灵活:替换Bean依赖对象,无需修改源文件:应用依赖注入后,由于可以采用配置
文件方式实现,从而能随时动态的替换Bean的依赖对象,无需修改java源文件;
2.更好实践面向接口编程,代码更清晰:在Bean中只需指定依赖对象的接口,接口定义依赖对象完成的功能,通过容
器注入依赖实现;
3.更好实践优先使用对象组合,而不是类继承:因为IoC容器采用注入依赖,也就是组合对象,从而更好的实践对象组
合。

? 采用对象组合,Bean的功能可能由几个依赖Bean的功能组合而成,其Bean本身可能只提供少许功能或根本无任何功能,全部委托给依赖
Bean,对象组合具有动态性,能更方便的替换掉依赖Bean,从而改变Bean功能;
? 而如果采用类继承,Bean没有依赖Bean,而是采用继承方式添加新功能,,而且功能是在编译时就确定了,不具有动态性,而且采用类继
承导致Bean与子Bean之间高度耦合,难以复用。

3.1代码结构如下

3.1构造器注入

HelloImpl代码如下
package com.springframe.springstudy.chapter3;

import com.springframe.springstudy.HelloApi;

public class HelloImpl implements HelloApi {

    private  String message;
    private  int index;

    public HelloImpl(String message, int index) {
        this.message = message;
        this.index = index;
    }

    public HelloImpl(){

    }

    @Override
    public void sayHello() {
        System.out.printf("helloImpl1:(message:"+this.message+",index:"+this.index+")");
    }
}

helloword.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 通过构造器参数索引方式依赖注入-->
    <bean id="byIndex" class="com.springframe.springstudy.chapter3.HelloImpl">
        <constructor-arg index="0" value="Hello World!"/>
        <constructor-arg index="1" value="1"/>
    </bean>
    <!-- 通过构造器参数类型方式依赖注入-->
    <bean id="byType" class="com.springframe.springstudy.chapter3.HelloImpl">
        <constructor-arg type="java.lang.String" value="Hello World!"/>
        <constructor-arg type="int" value="2"/>
    </bean>
    <!-- 通过构造器参数名称方式依赖注入-->
    <bean id="byName" class="com.springframe.springstudy.chapter3.HelloImpl">
        <constructor-arg name="message" value="Hello World!"/>
        <constructor-arg name="index" value="3"/>
    </bean>
</beans>
HelloImplTest测试代码如下
package com.springframe.springstudy.chapter3;

import com.springframe.springstudy.HelloApi;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

@SpringBootTest
public class HelloImplTest {

    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("chapter3/helloword.xml");
        HelloApi index = context.getBean("byIndex", HelloApi.class);
        HelloApi type = context.getBean("byType", HelloApi.class);
        HelloApi name = context.getBean("byName", HelloApi.class);
        index.sayHello();
        type.sayHello();
        name.sayHello();
    }
}

测试结果如下:

3.2讲解

1.、根据参数索引注入,使用标签

<constructor-arg index="1" value="1"/> ,index值1,代码构造器参数的索引位置(从0开始),value代表需要注入的值.

2.根据参数类型进行注入,使用标签

<constructor-arg type="int" value="2"/>,type的值代表参数的类型,value代表需要注入的值3.根据参数名进行注入,使用标签“<constructor-arg name="message" value="Hello World!"/>”来指定注入

的依赖,其中“name”表示需要匹配的参数名字,“value”来指定注入的常量值,

3.3使用静态工厂注入

在HelloImpl加上以下代码

public static HelloApi newInstance(String message,int index){
        return new HelloImpl(message,index);
    }

在helloword.xml加上以下代码

 <!-- 通过 静态工厂 构造器参数索引方式依赖注入-->
    <bean id="byIndexFactory" class="com.springframe.springstudy.chapter3.HelloImpl" factory-method="newInstance">
        <constructor-arg index="0" value="Hello World!  byIndexFactory"/>
        <constructor-arg index="1" value="1"/>
    </bean>

然后进行测试

 @Test
    public void testFactory() {
        ApplicationContext context = new ClassPathXmlApplicationContext("chapter3/helloword.xml");
        HelloApi indexFactory = context.getBean("byIndexFactory", HelloApi.class);
        indexFactory.sayHello();
    }

3.4通过setter方法注入

在helloword.xml加上以下代码(需要在HelloImpl中未index,message,写入setter方法)

 <!-- 通过 setter 构造器参数索引方式依赖注入-->
    <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl" >
       <property name="index" value="2"/>
        <property name="message" value="Hello World!  setter"/>
    </bean>

进行测试

@Test
    public void testSetter() {
        ApplicationContext context = new ClassPathXmlApplicationContext("chapter3/helloword.xml");
        HelloApi indexFactory = context.getBean("byIndexSetter", HelloApi.class);
        indexFactory.sayHello();
    }

3.5 注入集合、数组和字典

Spring不仅能注入简单类型数据,还能注入集合(Collection、无序集合Set、有序集合List)类型、数组(Array)类
型、字典(Map)类型数据、Properties类型数据

1、注入集合类型:包括Collection类型、Set类型、List类型数据

  集合list注入:

HelloImpl代码
package com.springframe.springstudy.chapter3;

import com.springframe.springstudy.HelloApi;

import java.util.Arrays;
import java.util.List;

public class HelloImpl implements HelloApi {

    private  String message;
    private  int index;

    private List<String> list;

    public HelloImpl(String message, int index) {
        this.message = message;
        this.index = index;
    }

    public HelloImpl(){

    }

    public static HelloApi newInstance(String message,int index){
        return new HelloImpl(message,index);
    }

    @Override
    public void sayHello() {
        System.out.println("helloImpl1:(message:"+this.message+",index:"+this.index+",list:"+ this.list+")");
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public void setList(List<String> list) {
        this.list = list;
    }
}

helloword.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 通过构造器参数索引方式依赖注入-->
    <bean id="byIndex" class="com.springframe.springstudy.chapter3.HelloImpl">
        <constructor-arg index="0" value="Hello World!"/>
        <constructor-arg index="1" value="1"/>
    </bean>
    <!-- 通过构造器参数类型方式依赖注入-->
    <bean id="byType" class="com.springframe.springstudy.chapter3.HelloImpl">
        <constructor-arg type="java.lang.String" value="Hello World!"/>
        <constructor-arg type="int" value="2"/>
    </bean>
    <!-- 通过构造器参数名称方式依赖注入-->
    <bean id="byName" class="com.springframe.springstudy.chapter3.HelloImpl">
        <constructor-arg name="message" value="Hello World!"/>
        <constructor-arg name="index" value="3"/>
    </bean>
    <!-- 通过 静态工厂 构造器参数索引方式依赖注入-->
    <bean id="byIndexFactory" class="com.springframe.springstudy.chapter3.HelloImpl" factory-method="newInstance">
        <constructor-arg index="0" value="Hello World!  byIndexFactory"/>
        <constructor-arg index="1" value="1"/>
    </bean>
    <!-- 通过 setter 构造器参数索引方式依赖注入-->
    <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl">
        <property name="index" value="2"/>
        <property name="message" value="Hello World!  setter"/>
        <property name="list">
            <list>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </list>
        </property>
    </bean>
</beans>

测试代码

 @Test
    public void testSetter() {
        ApplicationContext context = new ClassPathXmlApplicationContext("chapter3/helloword.xml");
        HelloApi indexFactory = context.getBean("byIndexSetter", HelloApi.class);
        indexFactory.sayHello();
    }

测试结果

set类型(HelloImpl类中加入属性:

private Collection<String> values;并写入对应的setter方法

)

 <!-- 通过 setter 构造器参数索引方式依赖注入-->
    <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl">
        <property name="index" value="2"/>
        <property name="message" value="Hello World!  setter"/>
        <property name="list">
            <list>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </list>
        </property>
        <property name="values">
            <set>
                <value>a</value>
                <value>b</value>
                <value>c</value>
            </set>
        </property>
    </bean>

2.注入数组

HelloImpl配置属性:private String[] array;并对应的setter方法

   <!-- 通过 setter 构造器参数索引方式依赖注入-->
    <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl">
        <property name="index" value="2"/>
        <property name="message" value="Hello World!  setter"/>
        <property name="list">
            <list>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </list>
        </property>
        <property name="values">
            <set>
                <value>a</value>
                <value>b</value>
                <value>c</value>
            </set>
        </property>
        <property name="array">
            <array>
                <value>array1</value>
                <value>array2</value>
            </array>
        </property>
    </bean>

3.map注入

 <!-- 通过 setter 构造器参数索引方式依赖注入-->
    <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl">
        <property name="index" value="2"/>
        <property name="message" value="Hello World!  setter"/>
        <property name="list">
            <list>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </list>
        </property>
        <property name="values">
            <set>
                <value>a</value>
                <value>b</value>
                <value>c</value>
            </set>
        </property>
        <property name="array">
            <array>
                <value>array1</value>
                <value>array2</value>
            </array>
        </property>
        <property name="map">
            <map>
                <entry>
                    <key><value>1</value></key>
                    <value>1</value>
                </entry>
                <entry>
                    <key><value>2</value></key>
                    <value>2</value>
                </entry>
            </map>
        </property>
    </bean>

4.properties注入

  <!-- 通过 setter 构造器参数索引方式依赖注入-->
    <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl">
        <property name="index" value="2"/>
        <property name="message" value="Hello World!  setter"/>
        <property name="list">
            <list>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </list>
        </property>
        <property name="values">
            <set>
                <value>a</value>
                <value>b</value>
                <value>c</value>
            </set>
        </property>
        <property name="array">
            <array>
                <value>array1</value>
                <value>array2</value>
            </array>
        </property>
        <property name="map">
            <map>
                <entry>
                    <key><value>1</value></key>
                    <value>1</value>
                </entry>
                <entry>
                    <key><value>2</value></key>
                    <value>2</value>
                </entry>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="key">key</prop>
                <prop key="key1">key1</prop>
            </props>
        </property>
    </bean>

5.引用其他的bean

用ref 标签

 <bean name="test" class="java.lang.String">
        <constructor-arg index="0" value="1111"/>
    </bean>
    <!-- 通过 setter 构造器参数索引方式依赖注入-->
    <bean id="byIndexSetter" class="com.springframe.springstudy.chapter3.HelloImpl">
        <property name="index" value="2"/>
        <property name="message" value="Hello World!  setter"/>
        <property name="list">
            <list>
               <ref bean="test"/>
                <value>2</value>
                <value>3</value>
            </list>
        </property>
        <property name="values">
            <set>
                <value>a</value>
                <value>b</value>
                <value>c</value>
            </set>
        </property>
        <property name="array">
            <array>
                <value>array1</value>
                <value>array2</value>
            </array>
        </property>
        <property name="map">
            <map>
                <entry>
                    <key><value>1</value></key>
                    <value>1</value>
                </entry>
                <entry>
                    <key><value>2</value></key>
                    <value>2</value>
                </entry>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="key">key</prop>
                <prop key="key1">key1</prop>
            </props>
        </property>
    </bean>

6.注入null值

  <property name="properties"><null></null>
        </property>

一、构造器注入:
1)常量值
简写:<constructor-arg index="0" value="常量"/>
全写:<constructor-arg index="0"><value>常量</value></constructor-arg>
2)引用
简写:<constructor-arg index="0" ref="引用"/>
全写:<constructor-arg index="0"><ref bean="引用"/></constructor-arg>
二、setter注入:
1)常量值
简写:<property name="message" value="常量"/>
全写:<property name="message"><value>常量</value></ property>
2)引用
简写:<property name="message" ref="引用"/>
全写:<property name="message"><ref bean="引用"/></ property>
3)数组:<array>没有简写形式
4)列表:<list>没有简写形式
5)集合:<set>没有简写形式
6)字典
简写:<map>
<entry key="键常量" value="值常量"/>
<entry key-ref="键引用" value-ref="值引用"/>
</map>
全写:<map>
<entry><key><value>键常量</value></key><value>值常量</value></entry>
http://jinnianshilongnian.iteye.com 1.4 【第三章】 DI 之 3.1 DI的配置使用 ——跟我学spring3
第 62 / 366 页
<entry><key><ref bean="键引用"/></key><ref bean="值引用"/></entry>
</map>
7)Properties:没有简写形式

延迟初始化Bean

延迟初始化也叫做惰性初始化,指不提前初始化Bean,而是只有在真正使用时才创建及初始化Bean。
配置方式很简单只需在<bean>标签上指定 “lazy-init” 属性值为“true”即可延迟初始化Bean。
Spring容器会在创建容器时提前初始化“singleton”作用域的Bean,“singleton”就是单例的意思即整个容器
每个Bean只有一个实例,后边会详细介绍。Spring容器预先初始化Bean通常能帮助我们提前发现配置错误,所以如果
没有什么情况建议开启,除非有某个Bean可能需要加载很大资源,而且很可能在整个应用程序生命周期中很可能使用不
到,可以设置为延迟初始化。
延迟初始化的Bean通常会在第一次使用时被初始化;或者在被非延迟初始化Bean作为依赖对象注入时在会随着初
始化该Bean时被初始化,因为在这时使用了延迟初始化Bean。
容器管理初始化Bean消除了编程实现延迟初始化,完全由容器控制,只需在需要延迟初始化的Bean定义上配置即
可,比编程方式更简单,而且是无侵入代码的。

<bean id="helloApi"
 class="cn.javass.spring.chapter2.helloworld.HelloImpl"
 lazy-init="true"/>

使用depends-on

depends-on是指指定Bean初始化及销毁时的顺序,使用depends-on属性指定的Bean要先初始化完毕后才初始
化当前Bean,由于只有“singleton”Bean能被Spring管理销毁,所以当指定的Bean都是“singleton”时,使用
depends-on属性指定的Bean要在指定的Bean之后销毁。

<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>
<bean id="decorator"
 class="cn.javass.spring.chapter3.bean.HelloApiDecorator"
depends-on="helloApi">
<property name="helloApi"><ref bean="helloApi"/></property>
</bean>

那“depends-on”有什么好处呢?主要是给出明确的初始化及销毁顺序,比如要初始化“decorator”时要确保
“helloApi”Bean的资源准备好了,否则使用“decorator”时会看不到准备的资源;而在销毁时要先在
“decorator”Bean的把对“helloApi”资源的引用释放掉才能销毁“helloApi”,否则可能销毁 “helloApi”时而
“decorator”还保持着资源访问,造成资源不能释放或释放错误

自动装配

自动装配就是指由Spring来自动地注入依赖对象,无需人工参与。
目前Spring3.0支持“no”、“byName ”、“byType”、“constructor”四种自动装配,默认是“no”指不支
持自动装配的,其中Spring3.0已不推荐使用之前版本的“autodetect”自动装配,推荐使用Java 5+支持的
(@Autowired)注解方式代替;如果想支持“autodetect”自动装配,请将schema改为“spring-beans-2.5.xsd”
或去掉。
自动装配的好处是减少构造器注入和setter注入配置,减少配置文件的长度。自动装配通过配置<bean>标签的
“autowire”属性来改变自动装配方式。接下来让我们挨着看下配置的含义。
一、default:表示使用默认的自动装配,默认的自动装配需要在<beans>标签中使用default-autowire属性指
定,其支持“no”、“byName ”、“byType”、“constructor”四种自动装配,如果需要覆盖默认自动装配

基本的作用域

一、singleton:指“singleton”作用域的Bean只会在每个Spring IoC容器中存在一个实例,而且其完整生命
周期完全由Spring容器管理。对于所有获取该Bean的操作Spring容器将只返回同一个Bean。

时间: 2024-10-11 03:13:25

学习spring容器IOC(3)之依赖和依赖注入的相关文章

Spring框架学习-Spring和IOC概述

一:什么是Spring框架? spring是一个分层的javase/EEfull-stack(一站式)轻量级的java开源框架.是为了解决企业开发的复杂性而创建的.框架的主要优势是分层架构,Spring的核心是控制反转(IOC)和面向切面(AOP). 二.学习Spring的好处? 主要就是方便解耦,简化开发 Spring就像一个工厂,可以将所有对象创建和依赖关系维护,都交给Spring管理. AOP编程的支持 Spring提供面向切面编程,可以方便的实现对程序进行权限拦截.运行监控等功能. 声明

spring容器IOC原理解析

原理简单介绍: Spring容器的原理,其实就是通过解析xml文件,或取到用户配置的bean,然后通过反射将这些bean挨个放到集合中,然后对外提供一个getBean()方法,以便我们获得这些bean.下面是一段简单的模拟代码: [java] view plain copy package com.tgb.spring.factory; import java.util.HashMap; import java.util.List; import java.util.Map; import or

Spring 容器IOC解析及简单实现

最近一段时间,"容器"两个字一直萦绕在我的耳边,甚至是吃饭.睡觉的时候都在我脑子里蹦来蹦去的.随着这些天一次次的交流.讨论,对于容器的理解也逐渐加深.理论上的东西终归要落实到实践,今天就借助Spring容器实现原理,简单说说吧. 简单的说,Spring就是通过工厂+反射将我们的bean放到它的容器中的,当我们想用某个bean的时候,只需要调用getBean("beanID")方法. 原理简单介绍: Spring容器的原理,其实就是通过解析xml文件,或取到用户配置的

容器学习(一):动手模拟spring的IoC

介绍 学习经典框架的实现原理以及设计模式在事实上际中的运用,是很有必要的,能够让我们更好进行面向对象. 本篇文章就来模拟Spring的IOC功能.明确原理后,能够更好的使用它,进而为进行面向对象提供一种思路. 点击下载源代码:下载 动手模拟IoC实现 首先我们把我们用的dao.service.entity定义出来: Student.java : package com.bzu.entity; public class Student { private int id; private Strin

如何把对象手动注入Spring容器并实现依赖注入

将对象注入到Spring容器并实现依赖注入 public class UserDao { @Resource AccountService accountService; public void print(){ System.out.println(accountService); } } 比如有以上这个类,实现将new UserDao()放入Spring容器中(放入工作由DefaultListableBeanFactory完成),并且AccountService会自动注入(注入工作由Auto

Spring的Ioc

引用:http://www.cnblogs.com/xdp-gacl/p/4249939.html 学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框架的IOC的理解以及谈谈我对Spring Ioc的理解. 一.分享Iteye的开涛对Ioc的精彩讲解 首先要分享的是Iteye的开涛这位技术牛人对Spring框

springMVC学习(什么是IOC)

接下来这段时间,我将会写一个关于springMVC的博客专栏,首先看看百度百科上是怎么定义springMVC的. Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来.它是为了解决企业应用开发的复杂性而创建的.框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用

Spring的IOC理解(转载)

学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框架的IOC的理解以及谈谈我对Spring Ioc的理解. 一.分享Iteye的开涛对Ioc的精彩讲解 首先要分享的是Iteye的开涛这位技术牛人对Spring框架的IOC的理解,写得非常通俗易懂,以下内容全部来自原文,原文地址:http://jinniansh

Spring中ioc的实现原理

学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框架的IOC的理解以及谈谈我对Spring Ioc的理解. 一.分享Iteye的开涛对Ioc的精彩讲解 首先要分享的是Iteye的开涛这位技术牛人对Spring框架的IOC的理解,写得非常通俗易懂,以下内容全部来自原文,原文地址:http://jinniansh