zoukankan      html  css  js  c++  java
  • 【Spring入门学习】

    一、IOC与DI

    • IOC: Inversion of Control —— 控制反转
      其思想是:反转资源获取的方向。传统的资源查找方式是要求组件向容器发起请求来查找资源,作为回应,容器会适时的返回资源;而IOC则是容器主动将资源推送到它所管理的组件,组件所要做的仅仅是选择用一种合适的方式来接受资源,这种方式也可称为查找的被动形式。
    • DI: Dependency Injection —— 依赖注入
      其实DI只是IOC的另一种表述方式,即组件以一些预定义好的方式(如 setter方法)接受来自容器的资源注入。相对于IOC来说,这种表述可能更加直接。

    二、Bean的配置

    1.配置形式: 基于XML文件的形式;基于注解的方式

    在xml文件中通过bean节点配置bean

    <bean id="helloWorld" class="com.spring.beans.HelloWorld">
    	<property name="name" value="Spring"></property> <!-- 需要有setter方法,对应name的方法是setName -->
    </bean>
    

    说明:
    class: Bean 的全类名,通过反射的方式在IOC容器中创建Bean,所以要求Bean中必须有无参的构造器.
    id: Bean的名称,标识容器中的bean, id必须是唯一的.
    id可以指定多个名字,可以使用 逗号、分号、空格 进行分隔. 如果没有指定,Spring会自动将权限定性类型作为Bean的名字.

    2.Bean的配置方式: 通过全类名(反射);通过工厂方法(静态工厂方法& 实例工厂方法);FactoryBean

    3.IOC容器: BeanFactory & ApplicationContext

    3.1 Spring提供了两种类型的IOC容器实现

    • BeanFactory: IOC容器的基本实现
    • ApplivationContext: 提供了更多的高级特性,是BeanFactory的子接口。

    说明:BeanFactory是Spring框架的基础设施,面向Spring本身;而ApplicationContext面向使用Spring框架的开发者,几乎所有的场合都是使用ApplicationContext而不是底层的BeanFactory.而且无论使用的是哪种方式,配置文件都是一样的。

    // 1.创建Spring的IOC容器对象
    // ApplicationContext代表IOC容器
    // ClassPathXmlApplicationContext是ApplicationContext接口的实现类,该实现类从类路径下加载配置文件
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    // 2.从容器中获取Bean实例
    HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");
    

    在Spring IOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化。只有在容器实例化之后,才可以从IOC容器里获取到Bean实例并使用。

    3.2 关于ApplicationContext(容器)

    • ApplicationContext的主要实现类:
      • ClassPathXmlApplicationContext: 从类路径下加载配置文件
      • FileSystemXmlApplicationContext: 从文件系统加载配置文件
    • ConfigurableApplicationContext是基于ApplicationContext扩展的,新增两个主要的方法:refresh()、close(), 让ApplicationContext具有启动、刷新、关闭上下文的能力。
    • ApplicationContext在初始化上下文时就会实例化所有单例的Bean.
    • WEBApplicationContext是专门为WEB应用而准备的,允许从相对于WEB根目录的路径中完成初始化工作。

    4.依赖注入的方式: 属性注入;构造器注入;工厂方式注入(很少使用,不推荐)

    4.1 属性注入

    • 属性注入是通过setter方法注入bean的属性值或依赖的对象。
    • 属性注入使用<property>元素,使用name属性指定bean的属性名称,value属性或者<value>子节点指定属性值。
    • 属性注入是实际使用中最常使用的注入的方式。
    <bean id="helloWorld" class="com.spring.beans.HelloWorld">
    	<property name="name" value="Spring"></property>
    </bean>
    
    package com.atguigu.spring.beans;
    
    public class HelloWorld {
    	private String name;
    
    	public void setName(String name) {
    		this.name = name;
    	}
    	
    	public void hello(){
    		System.out.println("hello: "+ name);
    	}
    }
    

    4.2 构造器注入

    • 通过构造方法注入Bean的属性值或者依赖的对象,它保证了bean实例在实例化之后可以使用。
    • 构造器注入是在<contructor-arg>元素里声明属性,这个元素中没有name属性,或者使用<value>子节点指定属性值。
    <!-- 通过构造方法配置bean的属性 -->
    <!-- 使用构造器注入属性值可以指定参数的位置和参数的类型,以区分重载的构造方法 -->
    <bean id="car" class="com.atguigu.spring.beans.Car">
    	<constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
    	<constructor-arg value="Shanghai" type="java.lang.String"></constructor-arg>
    	<constructor-arg value="300000" type="double"></constructor-arg>
    </bean>
    
    <bean id="car2" class="com.atguigu.spring.beans.Car">
    	<constructor-arg value="BMW" index="0"></constructor-arg>
    	<constructor-arg value="Huacheng" index="1"></constructor-arg>
    	<constructor-arg value="290" type="int"></constructor-arg>
    </bean>
    

    使用<value>子节点指定属性值:

    <bean id="car" class="com.atguigu.spring.beans.Car">
    	<constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
    	<constructor-arg value="Shanghai" type="java.lang.String"></constructor-arg>
    	<constructor-arg type="double">
    	    <value>300000</value>
    	</constructor-arg>
    </bean>
    

    4.3 字面值

    • 字面值是可以用字符串表示的值,可以通过元素标签或者value属性进行注入。
    • 基本数据类型及其封装类、String等类型都可以采用字面值注入的方式。
    • 如果字面值中包含特殊的字符,可以使用<![CDATA[]]>把字面值包裹起来。

    例如下面的配置文件中第二个参数是: <Shanghai>

    <bean id="car" class="com.atguigu.spring.beans.Car">
    	<constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
    	<constructor-arg type="java.lang.String">
    		<value><![CDATA[<Shanghai>]]></value>
        </constructor-arg>
    	<constructor-arg value="300000" type="double"></constructor-arg>
    </bean>
    

    4.4 引入其他的Bean

    组成应用程序的bean经常要相互协作来完成程序的功能。要是bean能够相互访问,就必须在bean配置文件中指定对bean的应用。
    在bean的配置文件中,可以通过<ref>元素或ref属性来为bean的属性或构造器参数指定对bean的引用。也可以在属性或构造器里包含bean的声明,这样的bean称为内部bean(不能被外部引用).

    当Bean的实例仅仅是给一个特定的属性使用,可以将它声明为内部bean,内部bean的声明包含在或者元素里,不需要设置任何id或name属性;内部bean不能放在任何其他地方

    <bean id="person" class="com.atguigu.spring.beans.Person">
    	<property name="name" value="Tom"></property>
    	<property name="age" value="27"></property>
    	<!-- 可以使用property的ref属性建立bean之间的引用关系 -->
    	<property name="car" ref="car2"></property> 
    	
    	<!-- 使用ref元素标签
    	<property name="car">
    		<ref bean="car2" />
    	</property>
    	-->
    	
    	<!-- 使用内部bean 内部bean的id是可以不用写的,因为它不能被外部引用
    	<property name="car">
    		<bean class="com.atguigu.spring.beans.Car">
    			<constructor-arg value="Ford" index="0"></constructor-arg>
    			<constructor-arg value="ChangAn" index="1"></constructor-arg>
    			<constructor-arg value="240" type="int"></constructor-arg>
    		</bean>
    	</property>
    	-->
    </bean>
    

    4.4 null值与级联属性

    可以使用专门的<null/>元素标签为Bean的字符串或者其他对象类型的属性注入null值,和Struts、Hibernate等框架一样,Spring也支持级联属性的配置。

    <bean id="person" class="com.atguigu.spring.beans.Person">
    	<property name="name" value="Tom"></property>
    	<property name="age" value="27"></property>
    	<!-- 可以使用property的ref属性建立bean之间的引用关系 -->
    	<property name="car" ref="car2"></property> 
    	<!-- 为级联属性赋值 注意:属性需要先初始化后才可以为级联属性赋值-->
    	<property name="car.price" value="400000"></property> 
    </bean>
    

    4.5 集合属性

    在Spring中可以使用一组xml标签,比如<list>,<set>, <map>来配置集合属性。

    • 配置java.util.List类型的属性,需要指定标签,在标签里包含一些元素,这些标签可以通过指定简单的常量值,通过指定对其他Bean的引用,通过指定内置的bean定义,通过指定空元素,甚至可以嵌入其他集合。
    • 数组的定义和List一样,都是使用
    <!-- 测试配置集合属性 -->
    <bean id="person3" class="com.spring.beans.collection.PersonList">
    	<property name="name" value="Mike"></property>
    	<property name="age" value="27"></property>
    	<property name="cars">
    		<!-- 使用list节点 -->
    		<list>
    			<ref bean="car" />
    			<ref bean="car2" />
    		</list>
    	</property>
    </bean>
    
    • 配置java.util.Set需要使用标签,定义元素的方法同List.
    • java.util.Map通过<map>标签以及其子标签<entry>定义,每个条目包含一个键和一个值。键和值的类型没有限制,可以自由的指定为<value>,<ref>,<bean>,<null>。可以将Map的键和值作为<entry>的属性定义:简单常量使用key/value来定义,Bean引用通过key-ref/value-ref属性定义。
    <!-- 测试配置Map属性值 -->
    <bean id="person4" class="com.spring.beans.collection.PersonMap">
    	<property name="name" value="Shih"></property>
    	<property name="age" value="27"></property>
    	<property name="cars">
    		<!-- 使用map节点以及entry子节点配置 -->
    		<map>
    			<entry key="AA" value-ref="car"></entry>
    			<entry key="BB" value-ref="car2"></entry>
    		</map>
    	</property>
    </bean>
    
    • 使用<props>定义java.util.Properties,这个标签使用多个<prop>作为子标签,每个<prop>标签必须要定义key属性。(用的比较多,在整合Hibernate时会用到)
    <!-- 配置Properties属性赋值 -->
    <bean id="dataSource" class="com.spring.beans.collection.DataSource">
    	<property name="properties">
    		<props>
    			<prop key="user">root</prop>
    			<prop key="passwd">root1234</prop>
    			<prop key="jdbcUrl">jdbc:mysql:///test</prop>
    			<prop key="driverClass">com.mysql.jdbc.Driver</prop>
    		</props>
    	</property>
    </bean>
    

    注意: 这里创建了另一个包:com.spring.beans.collection,而在配置文件中引用了com.spring.beans中的类,所以需要在com.spring.beans.collection.PersonList/ PersonMap中 import com.spring.beans.Car;类才可以。

    • 配置单例的集合bean 以供多个bean进行引用,需要导入util命名空间
      说明:使用基本的集合标签定义集合时,不能够将集合作为一个独立的Bean定义,所以也就导致其他的bean无法共用这个集合,我们可以使用util schema里的集合标签定义独立的集合bean,需要注意的是必须在<beans>根元素里添加util schema定义。(其实就是上面容易理解的简单的一句话)
    <util:list id="cars">
    	<ref bean="car"/>
    	<ref bean="car2"/>
    </util:list>
    
    <bean id="person5" class="com.spring.beans.collection.PersonList">
    	<property name="name" value="utilNameSpace"></property>
    	<property name="age" value="27"></property>
    	<property name="cars" ref="cars"></property>
    </bean>
    

    4.6 使用p命名空间

    为了简化XML文件的配置信息,越来越多的XML文件采用属性而非子元素配置信息。
    Spring 从2.5版本开始引入了一个新的p命名空间,可以通过<bean>元素属性的方式配置bean的属性。
    使用p命名空间之后,基于XML的配置方式可以进一步简化。

    <!-- 通过p命名空间为bean的属性赋值,需要先导入p命名空间 -->
    <bean id="person6" class="com.spring.beans.collection.PersonList" p:name="shiddong" p:age="30" p:cars-ref="cars">
    </bean>
    

    5.自动装配

    • Spring IOC容器可以自动装配bean,需要做的仅仅是<bean>的autowire属性里指定自动装配的模式
    • byType(根据类型自动装配):如果IOC容器中有多个与目标Bean类型一致的Bean,在这种情况下,Spring将无法判断那个bean最合适这个属性,所以不能执行自动装配。
    • byName(根据名称自动装配):必须将目标bean的名称和属性名设置的完成相同。
    • constructor(通过构造器自动装配):当bean中存在多个构造器时,这种自动装配方式会很复杂,一般不推荐使用
    <bean id="address" class="com.atguigu.spring.beans.autowire.Address" p:city="Shanghai" p:street="Shangpu"></bean>
    <bean id="car" class="com.atguigu.spring.beans.autowire.Car" p:brand="Audi" p:price="300000"></bean>
    <!-- <bean id="person" class="com.atguigu.spring.beans.autowire.Person" p:name="Tom" p:address-ref="address" p:car-ref="car"></bean>-->
    
    <!-- autowire自动装配,byName根据bean的名字和当前的bean的setter风格的属性名进行自动装配 -->
    <!-- 若有匹配的,就会进行自动装配;如果没有匹配的,就不装配 -->
    <bean id="person" class="com.atguigu.spring.beans.autowire.Person" p:name="Shih" autowire="byName"></bean>
    
    <!-- byType根据bean的类型和当前的bean的属性的类型进行自动装配 有一个问题:如果IOC容器中有1个以上的类型匹配的bean,就会抛出异常-->
    

    XML配置里的bean自动装配其实是有很多缺点的
    1.在bean配置文件里设置autowire进行自动装配将会装配bean的所有属性。然而,如果我们只希望抓高配个别属性时,autowire就不够灵活了。
    2.autowire属性要么根据类型自动装配,要么根据名称自动装配,不能两者同时使用。
    3.一般情况下,在实际的项目中很少使用自动装配供呢个,因为和自动装配带来的好处相比,明确清晰的配置文档更有说服力一些。

    6.bean之间的关系:继承; 依赖

    7.bean的作用域:singleton; prototype; WEB环境作用域

    8.使用外部属性文件

    9.SpEL

    10.IOC容器中Bean的生命周期

    11.Spring 4.x新特性: 泛型依赖注入

  • 相关阅读:
    Android Studio如何设置代码自动提示
    Java中Map的用法详解
    Android 管理Activity中的fragments
    Android
    WebApp之Meta标签
    iOS中为网站添加图标到主屏幕以及增加启动画面
    HTML5添加 video 视频标签后仍然无法播放的解决方法 IIS添加MIEI类型
    WebApp之 apple-touch-icon
    Eclipse编辑器基本设置
    Redis监控方案
  • 原文地址:https://www.cnblogs.com/shih/p/6980453.html
Copyright © 2011-2022 走看看