Spring学习(一)---依赖注入和控制反转

Spring

  Spring是一个从实际开发中抽出来的框架,因此它完成了大量开发中的通用步骤,留给开发者的仅仅是与特定应用相关的部分,从而大大提高了企业应用的开发效率。

  Spring为企业应用的开发提供了一个轻量级的解决方案。该解决方案包括:基于依赖注入的核心机制、基于AOP的声明事务管理、与多种持久层技术的整合,以及优秀的Web MVC框架等。

使用Spring管理Bean

  Spring核心容器就是一个超级大工厂,所有的对象(包括数据源、Hibernate SessionFactory等基础性资源)都会被当成Spring核心容器管理的对象--Spring把容器中的一切对象统称为Bean。

  Spring容器中的Bean,与Java Bean不同(Java Bean必须遵守一些特定的规范),Spring对Bean没有任何要求。只要是一个Java类,Spring就可以管理该Java类,并将它当成Bean处理。

配置Bean

<bean id=”对象名” class=”全限定类名”>
    <property name=”属性名” ref=”被依赖的Bean的对象名” />
</bean>

  Spring配置Bean时,class属性的值必须是Bean实现类的完整类名,不能是接口,不能是抽象类,否则Spring无法使用反射创建该类的实例。

  <property …/>子元素用于作为<bean …/>元素的子元素,它驱动Spring在底层以反射执行一次setter方法。name属性决定执行哪个setter方法,而value或ref决定执行setter方法的传入参数。如果传入的参数是基本类型或者其包装类、String等类型。则使用value属性指定传入参数。如果以容器中其他Bean作为传入参数,则使用ref属性指定传入参数。

  <bean …/>元素的作用是:默认驱动Spring在底层调用无参构造函数创建对象。

  Spring框架只要看到<property …/>子元素,Spring框架就会在底层以反射方式执行一次setter方法。何时执行这个setter方法呢?

  该Bean一旦创建处理,Spring会立即根据<property …/>子元素来执行setter方法。

通过Spring容器中访问容器中的Bean,ApplicationContext是Spring容器中最常用的接口。该接口有两个实现类:

  ClassPathXmlApplicationContext:从类加载路径下搜索配置文件,并根据配置文件来创建Spring容器。

  FileSystemXmlApplicationContext:从文件系统的相对路径或绝地路径下去搜索配置文件,并根据配置文件来创建Spring容器。

//创建Spring容器
ApplicationContextctx = new ClassPathXmlApplicationContext(“配置文件名”);

  Spring容器获取Bean对象主要有如下两个方法:

  Object getBean(String id):根据容器中Bean的id来获取指定的Bean,获取Bean之后需要进行强制类型转换。

  T getBean(String name,Class<T>):根据容器中的Bean的id来获取指定Bean,但该方法带一个泛型参数,因此获取Bean之后无须进行强制类型转换。

  Spring框架最大的改变之一是程序不再使用new调用构造器创建Java对象,所有Java对象都由Spring容器负责创建。

Spring容器

  Spring有两个核心接口:BeanFactoryApplicationContext,其中ApplicationContext是BeanFactory的子接口。他们都可代表Spring容器,Spring容器是生成Bean实例的工厂,并管理容器中的Bean。

  Spring容器创建对象的时机

  默认为启动时创建Bean实例,为Bean配置一个bean,只创建一个对象,在底层使用了单例模式。

  使用bean元素的属性 lazy-init = “true” 延迟加载(懒加载),lazy-init 和scope = “singleton” 结合使用。

  Bean配置一个bean元素,每次创建一个新的对象,而不是使用时一个对象时,需要为bean元素配置 scope = "prototype"

  prototype:每次通过容器的getBean()方法获取prototype作用域的Bean时,都将产生一个新的Bean实例。

Spring核心机制:依赖注入

  依赖注入:简单的来说,A对象要调用B对象中的方法,也就可以说A依赖于B。

  Spring框架的核心功能有两个:

  ①Spring容器作为超级大工厂,负责创建、管理所有的Java对象(Bean)

  ②Spring容器管理容器中Bean之间的依赖关系,Spring使用一种“依赖注入”的方式来管理Bean之间的依赖关系。

  依赖注入是一种优秀的解耦方式。依赖注入让Spring的Bean以配置文件组织在一起,而不是以硬编码的方式耦合在一起。使用Spring框架,调用者获取被依赖对象的方式由原来的主动获取,变成了被动接受,被称为控制反转。

  从Spring容器的角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,相当于为调用者注入它依赖的实例,被称为依赖注入

  控制反转和依赖注入其实是同一个行为的两种表达方式,只是描述的角度不同而已。

举一个通俗易懂的例子

  一个人(Java实例,调用者)需要斧头(Java实例,被依赖对象)来干活。

  在原始社会,需要斧头的人(调用者)只能自己去磨一把斧头(被依赖对象)。对应的情形为:Java程序里的调用者自己创建被依赖对象,通常采用new关键字调用构造器创建一个被依赖对象。

  进入工业社会,工厂出现了,斧头不再由普通人完成,而在工厂里被生成出来,此时需要斧头的人(调用者)找到工厂,购买斧头,无须关心斧头的制造过程。对应简单的工厂设计模式,调用者只需定位工厂,无须理会被依赖对象的具体实现过程。

  进入共产主义社会,需要斧头的人甚至无须定义工厂,“坐等”社会提供即可。调用者无须关心被依赖对象的实现,无须理会工厂,等待Spring依赖注入。

依赖注入通常有两种

设值注入:IoC容器使用成员变量的setter方法来注入被依赖对象。

构造注入:IoC容器使用构造器来注入被依赖对象。

设值注入

  这种注入方式简单,直观,在Spring的依赖注入中大量使用。

  下面的例子集成了设值注入的各种情形,如为基本类型,数组,引用数组,List,Set,Map,和Properties属性注值。

public class Student {
  //标志属性
  private int id;
  //学生编号
    private String stuNo;
    //学生姓名
    private String stuName;
    //学生爱好
    private String[] hobbys;
    //喜欢的演员
    private Actor[] actors;
    //上过的学校
   private List<String> schools;
   //爱听的歌
    private Set<String> songs;
    //代课的老师
    private List<Teacher> techers;
    //选的课程
    private Set<Course> course;
    //联系方式
  private Map<String,String> links;
  //课程成绩
    private Map<Course,String> scores;
    //健康状况
    private Properties health;

    //省略了setter和getter方法

}
public class Actor {
    private int id;
    private String actName;
//省略了setter和getter方法
}
public class Teacher {
    private int id;
    private String teaNo;
    private String teaName;
//省略了setter和getter方法
}
public class Course {
    private int id;
    private String courNo;
    private String courName;
//省略了setter和getter方法
}

在application.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">

    <!-- 创建teacher对象,并注入值-->
    <bean id="teacher1" class="com.ghq.model.entity.Teacher">
        <property name="id" value="1"/>
        <property name="teaNo" value="t001"/>
        <property name="teaName" value="杨教授"/>
    </bean>
    <bean id="teacher2" class="com.ghq.model.entity.Teacher">
        <property name="id" value="2"/>
        <property name="teaNo" value="t002"/>
        <property name="teaName" value="李教授"/>
    </bean>

    <!-- 创建course对象,并注入值-->
    <bean id="course1" class="com.ghq.model.entity.Course">
        <property name="id" value="1"/>
        <property name="courNo" value="c001"/>
        <property name="courName" value="数据结构"/>
    </bean>
    <bean id="course2" class="com.ghq.model.entity.Course">
        <property name="id" value="2"/>
        <property name="courNo" value="c002"/>
        <property name="courName" value="计算机网络"/>
    </bean>

    <!-- 创建actor对象,并注入值-->
    <bean id="actor1" class="com.ghq.model.entity.Actor" >
        <property name="id" value="1"/>
        <property name="actName" value="薛之谦"/>
    </bean>
    <bean id="actor2" class="com.ghq.model.entity.Actor" >
        <property name="id" value="2"/>
        <property name="actName" value="周杰伦"/>
    </bean>

    <!-- 创建student对象,并注入值-->
    <bean id="student" class="com.ghq.model.entity.Student">
        <!-- 基本类型,String等赋值-->
        <property name="id" value="1"/>
        <property name="stuNo" value="s001"/>
        <property name="stuName" value="张三"/>

        <!-- 基本类型数组赋值-->
        <property name="hobbys">
            <array>
                <value>睡觉</value>
                <value>打游戏</value>
            </array>
        </property>

        <!-- 引用类型数组赋值-->
        <property name="actors">
            <array>
                <ref bean="actor1"/>
                <ref bean="actor2"/>
            </array>
        </property>

        <!-- list集合(基本类型)赋值-->
        <property name="schools">
            <list>
                <value>清华大学</value>
                <value>北京大学</value>
            </list>
        </property>
        <!-- set集合(基本类型)赋值-->
        <property name="songs">
            <set>
                <value>小苹果</value>
                <value>我们不一样</value>
            </set>
        </property>

     <!-- list集合(引用类型)赋值-->
        <property name="techers">
            <list>
                <ref bean="teacher1"/>
                <ref bean="teacher2"/>
            </list>
        </property>

        <!-- set集合(引用类型)赋值-->
        <property name="course">
            <set>
                <ref bean="course1"/>
                <ref bean="course2"/>
            </set>
        </property>

        <!-- map集合(基本类型)赋值-->
        <property name="links">
            <map>
                <entry key="phone" value="1234567890"></entry>
                <entry key="QQ" value="987654"></entry>
            </map>
        </property>

        <!-- map集合(引用类型)赋值-->
        <property name="scores">
            <map>
                <entry key-ref="course1" value="88"></entry>
                <entry key-ref="course2" value="77"></entry>
            </map>
        </property>

        <!-- Properties类型赋值-->
        <property name="health">
            <props>
                <prop key="height">170</prop>
                <prop key="weight">130</prop>
            </props>
        </property>
    </bean>

</beans>

测试输出结果为

public class Test {
    public static void main(String[] args) {
        ApplicationContext fac = new ClassPathXmlApplicationContext("application.xml");
        Student stu = fac.getBean("student", Student.class);
        System.out.println(stu.toString());  }}

Student,Actor,Course,Teacher中均有toString方法,将属性一次性输出

运行结果为:

Student [id=1, stuNo=s001, stuName=张三, hobbys=[睡觉, 打游戏], actors=[Actor [id=1, actName=薛之谦], Actor [id=2, actName=周杰伦]], schools=[清华大学, 北京大学], songs=[小苹果, 我们不一样], techers=[Teacher [id=1, teaNo=t001, teaName=杨教授], Teacher [id=2, teaNo=t002, teaName=李教授]], course=[Course [id=1, courNo=c001, courName=数据结构], Course [id=2, courNo=c002, courName=计算机网络]], links={phone=1234567890, QQ=987654}, scores={Course [id=1, courNo=c001, courName=数据结构]=88, Course [id=2, courNo=c002, courName=计算机网络]=77}, health={height=170, weight=130}]

构造注入

  这种方式在构造实例时,已经为其完成了依赖关系的初始化。这种利用构造器来设置依赖关系的方式,称为构造注入。

  通俗来讲就是通过Spring在底层以反射方式执行带指定参数的构造器,当执行带参数的构造器时,就可利用构造参数对成员变量执行初始化。

  使用构造注入,在类中不用提供setter方法,提供带参数的构造器。

<bean id=”对象名” class=”全限定类名”>
    <constructor-arg ref=”参数” />
</bean>

原文地址:https://www.cnblogs.com/ghq120/p/8327701.html

时间: 2024-10-09 22:11:02

Spring学习(一)---依赖注入和控制反转的相关文章

Spring4.3学习之依赖注入和控制反转

直接值引用: idref元素: idref只是简单的以误差检测的方式将容器中其他bean的id(字符串值而非引用bean)传递给<constructor-arg/> 或 <property/> 元素可以检测bean是否已经存在,类似于value属性,但是比其更好,因为能在容器部署时检查所引用http://i.cnblogs.com/EditPosts.aspx?opt=1bean是否已经存在. 注意,从4.0开始不再支持idref元素的local属性,因为其不支持正则形式的参考be

Spring 的核心机制:依赖注入(控制反转)

一.说到依赖注入(控制反转),先要理解什么是依赖. Spring 把相互协作的关系称为依赖关系.假如 A 组件调用了 B 组件的方法,我们可称A 组件依赖于 B 组件. 二.什么是依赖注入. 在传统的程序设计过程中,通常由调用者来创建被调用者的实例. 在依赖注入的模式下,创建被调用者的工作不再由调用者来完成,因此称为控制反转:创建被调用者实例的工作通常由Spring 容器来完成,然后注入给调用者,因此也称为依赖注入. 三.依赖注入的好处. 依赖注入让 Spring 的 Bean 以被指文件组织在

简单解析依赖注入(控制反转)在Spring中的应用

IoC——Inversion of Control  控制反转DI——Dependency Injection   依赖注入 大家都知道,依赖注入是Spring中非常重要的一种设计模式.可能很多初学者对这种看起来高深的东西有一种抗拒,这里就 简单介绍一下到底什么是依赖注入,Spring到底又到底是如何运用依赖注入的. 依赖关系:在A组件中要引用B组件的对象,则称A依赖于B依赖关系会造成各组件之间的硬编码,为解决依赖关系,一般的解决方法如下: 1.A组件先创建B组件,在调用B组件方法2.A组件先通

【AutoFac】依赖注入和控制反转的使用

在开始之前首先解释一下我认为的依赖注入和控制反转的意思.(新手理解,哪里说得不正确还请指正和见谅) 控制反转:我们向IOC容器发出获取一个对象实例的一个请求,IOC容器便把这个对象实例“注入”到我们的手中,在这个时候我们不是一个创建者,我们是以一个请求者的身份去请求容器给我们这个对象实例.我们所有的对象依赖于容器提供给你的资源,控制权落到了容器身上.在这里的身份转化或许就是控制反转的核心吧. 依赖注入:我们向容器发出请求以后,获得这个对象实例的过程就叫依赖注入.也就是我们在使用对向前我们都需要先

谈谈php依赖注入和控制反转

要想理解php依赖注入和控制反转两个概念,就必须搞清楚如下的问题: DI--Dependency Injection   依赖注入 IoC--Inversion of Control  控制反转 1.参与者都有谁? 答:一般有三方参与者,一个是某个对象:一个是IoC/DI的容器:另一个是某个对象的外部资源.又要名词解释一下,某个对象指的就是任意的.普通的Java对象; IoC/DI的容器简单点说就是指用来实现IoC/DI功能的一个框架程序:对象的外部资源指的就是对象需要的,但是是从对象外部获取的

反射机制、依赖注入、控制反转

反射机制 正向: 代码->dll, 先编码, 定义好类,通过实例化对象来调用之. 反向: dll->类[方法,属性]. 从已经有的dll文件反编译得到其中的一些可用的方法. 审查元数据并收集关于它的类型信息的能力.元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等. System.reflection命名空间包含的几个类,允许你反射(解析)这些元数据表的代码. 反射是.Net中获取 运行时类型信息的方式,.Ne

依赖注入和控制反转

依赖注入: A类依赖着B类,如下: public A{ private B b; public void showB(){ b= new B(); System.out.println(b); } } 我们可以通过spring配置或者注解的方式去注入依赖类,从而做到每次使用依赖类时无须手动去实例化依赖类,这就是所谓的依赖注入. 控制反转: 我们通过spring提供的ApplicationContext对象(代表一个spring控制反转容器)去控制去操作容器中的类,而不是以往我们自己去创建类去操作

依赖注入与控制反转的理解

控制反转与依赖注入 定义 控制反转(IoC/Inverse of Control): 调用者不再创建被调用者的实例,而是由spring框架实现(容器创建)所以称为控制反转. 依赖注入(DI/Dependency injection): 容器创建好实例后再注入到调用者称为依赖注入. 当某个角色(调用者)需要另外一个角色(被调用者)的协助时,在传统的程序设计过程中,通常由调用者创建被调用者的实例.如果创建被调用者实例的工作不再由调用者来完成,而是由外部容器完成,因此称为控制反转:创建调用者的工作通常

浅谈依赖注入与控制反转

前言:设计模式其实是一个很空洞的东西,设计模式有几十种,有些人觉得工厂模式也单例模式已经足够解决大部分问题.而有些人觉得任何设计模式都会让开发变得更“复杂”,更“低效”.所以千万不要太过追求他的实际意义和作用,否则你已经坠入云雾.但是不管怎么样,实际工作中还是要对它们有所了解,下面从php的角度来讲一下依赖注入.控制反转.反射等概念.如有错误之处,还望路过大神多加指点 首先设定场景,假如一个类需要数据库连接,最简单的做法可能是: class example { private $_db; fun