一、Spring IOC是什么

1.简述

Spring是一个开源框架

Spring为简化企业级应用开发而生,使用Spring可以使简单的JavaBean实现以前只有EJB才能实现的功能

Spring是一个IOC(DI)和AOP容器框架

2.特性描述

轻量级:Spring是非侵入式的,基于Spring开发的应用中对象可以不依赖于Spring的API

依赖注入(DI—dependency injection、IOC)

面向切面编程(AOP—aspect oriented programming)

容器:Spring是一个容器,因为它包含并管理应用对象的生命周期

框架:Spring实现了使用简单的组件配置组合成一个复杂的应用,在Spring中可以使用XML和java注解组合这些对象

一站式:在IOC和AOP的基础上可以整合各种企业级应用的开源框架和优秀的第三方应用(实际上Spring自身也提供了展现

层的SpringMVC和持久层的Spring JDBC)

3.IOC和DI概述

IOC:其思想是反转资源获取的方向,传统的资源查找方式要求组件向容器发起请求查找资源,作为回应,容器适时的返回资源,而应用

了IOC之后,则是容器主动地将资源推送给它所管理的组件,组件所要做的就是选择一种合适的方式接受资源,这种行为被称为查找的被动形式。

DI:IOC的另一种表述形式:即组件以一些预先定义好的方式(例如:setter方法)接受来自容器的资源注入,相对于IOC而言,

这种表述更直接。

4.如何配置Bean

        ——IOC容器BeanFactory、ApplicationContext概述
——配置形式:基于xml文件的方式、基于注解的方式
——Bean的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法&实例工厂方法)、FactoryBean
——依赖注入的方式:属性注入、构造器注入
——属性注入细节
——自动装配
——Bean之间的关系:继承、依赖
——Bean的作用域:singleton、prototype、web环境作用域
——使用外部属性文件
——spEL
——IOC容器中Bean的生命周期
Spring4.x新特性:泛型依赖注入

5.Spring容器

①在Spring容器读取Bean配置创建Bean实例之前,必须对它进行实例化,只有在容器实例化之后,才可以从容器中获取Bean实例
并使用。
②Spring提供了两种类型的IOC容器实现:Beanfactory、ApplicationContext。
③BeanFactory是Spring框架的基础设施,面向Spring本身
④ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都直接使用ApplicationContext而
非底层的Beanfactory,无论使用那种方式,配置文件都是相同的。
⑤ApplicationContext:有两个实现类
——ClassPathXmlApplicationContext:从类路径下加载配置文件
——FileSystemXmlApplicationContext:从文件系统中加载配置文件

6.依赖注入的方式

Spring支持3种依赖注入的方式

属性注入、构造器注入、工厂方法注入很少使用,不推荐)

①属性注入:即通过setter方法注入Bean的属性或依赖的对象,属性注入使用<property>
元素,使用name属性指定Bean的属性名称,value属性或<value>子节点指定属性值,属性注入是
最长用的注入方式。
<bean id="helloWorld class="com.test.spring.bean.HelloWorld">
<!-- name的值对应着,类HelloWorld中的setName()方法 -->
<property name="name" value="Spring"></property>
</bean>
②通过构造方法注入Bean的属性或依赖的对象,它保证了Bean的实例在实例化之后就可以使用,
构造器注入在<constructor-arg>元素里声明属性,<constructor-arg>中没有name属性
③通过调用静态工厂方法创建Bean
调用静态工厂方法创建 Bean是将对象创建的过程封装到静态方法中. 当客户端需要对象时, 只需要简单地调用静态方法, 而不同关心创建对象的细节,要声明通过静态方法创建的 Bean, 需要在 Bean 的 class 属性里指定拥有该工厂的方法的类, 同时在 factory-method 属性里指定工厂方法的名称. 最后, 使用 <constrctor-arg> 元素为该方法传递方法参数
class:指向工厂方法的全类名
factory-method:指向静态方法的名称
<constructor-arg>:元素如果工厂方法需要传入参数,则使用它来配置参数
<!-- 通过静态工厂方法来配置Bean,注意不是配置静态工厂方法实例,而是配置Bean实例 -->
<bean id="car2" class="com.test.spring.BeanFactory.StaticCarFactory"
factory-method="getCar">
<constructor-arg value="audi"></constructor-arg>
</bean> ④通过FactoryBean配置Bean
class:指向FactoryBean的全类名
property:配置factoryBean的属性
但实际返回的是实例确实FactoryBean的getObject()方法返回的实例
<bean id="car4" class="com.test.spring.BeanFactory.CarFactoryBean">
<property name="brand" value="BMW"></property>
</bean> ⑤配置引用其他的Bean
组成应用程序的Bean经常要相互协作以完成应用程序的功能,要是Bean能够互相访问,就必须在Bean的配置文件中指定对Bean应用
<ref>元素或ref属性:为Bean的属性和构造器参数指定对Bean的引用
⑥内部Bean:在属性和构造器中包含Bean的声明,内部Bean不能够被外部Bean引用配置级联属性 ⑦配置集合属性
在Spring中可以通过一组内置的的xml标签(例如:<list>、<set>、<map>)来配置集合属性。
List:配置java.uitl.List类型的元素属性,需要指定<list>标签,在标签里包含一些元素,这些标签可以通过
<value>指定简单的常量值,通过<ref>指定对其他Bean的引用,通过<Bean>指定内置的Bean定义,通过<null/>
指定空元素,甚至是内嵌其他集合。
<bean id="person3" class="com.test.spring.ListBeans.ListPersons">
<property name="name" value="Mike"></property>
<property name="age" value="22"></property>
<property name="cars">
<list>
<ref bean="car"/>
<ref bean="car2"/>
<ref bean="car3"/>
<!-- 也可以使用内部Bean -->
<bean class="com.test.spring.bean.Car">
<constructor-arg value="Audi"></constructor-arg>
<constructor-arg value="QQ"></constructor-arg>
<constructor-arg value="320000"></constructor-arg>
<constructor-arg value="220"></constructor-arg>
</bean>
</list>
</property>
</bean> set集合的配置类似List。 map集合:通过<map>标签定义,<map>标签中可以使用多个<entry>作为子标签,每个条目包含一堆键值对
必须有<key>标签里定义键,因为键和值的类型没有限制,可以自由的为他们指定<value>、<ref>、<bean>、<null>元素。
可以将Map的键和值作为<entry>的属性定义:简单常量使用key和value来定义,Bean的引用使用<key-ref>
和<value-ref>属性定义,使用<props>定义java.util.Properties该标签使用多个<prop>作为子标签,
每个<prop>标签必须定义key属性。
<bean id="person4" class="com.test.spring.ListBeans.MapPersons">
<property name="name" value="Rose"></property>
<property name="age" value="30"></property>
<property name="cars">
<map>
<entry key="AA" value-ref="car"></entry>
<entry key="BB" value-ref="car2"></entry>
<!-- 也可以使用内部Bean -->
</map>
</property>
</bean> 配置Properties属性值:
<bean id="dataSource" class="com.test.spring.ListBeans.DataSource">
<property name="properties">
<props>
<prop key="user">root</prop>
<prop key="password">root</prop>
<prop key="jdbcUrl">jabc:mysql:///test</prop>
<prop key="driverClass">com.mysql.jabc.Driver</prop>
</props>
</property>
</bean>
使用utility scheme定义集合:使用基本的集合标签定义集合时,不能将集合作为独立的Bean定义,导致其他Bean
无法引用该集合,所以无法在不用的Bean之间共享集合,可以使用utility scheme里的集合标签定义独立的集合Bean
需要注意的是,必须在<Beans>根元素里添加util scheme定义。
<!-- ④引用集合Bean,配置一个单独的集合Bean,以供其他Bean引用,需要导入util命名空间 -->
<util:list id="cars">
<ref bean="car"/>
<ref bean="car2"/>
<ref bean="car3"/>
</util:list>
<!-- 引用以上的cars -->
<bean id="person5" class="com.test.spring.ListBeans.ListPersons">
<property name="name" value="Jack"></property>
<property name="age" value="23"></property>
<property name="cars" ref="cars"></property>
</bean> ⑧使用p命名空间,为了简化XML文件的配置,越来越多的XML文件采用属性而非子元素配置信息,Spring2.5版本开始
引用一个新的p命名空间,可以通过<Bean>元素属性的方式,配置Bean的属性,使用命名空间后,基于XML的配置方式将
进一步简化。
<bean id="person6" class="com.test.spring.ListBeans.ListPersons" p:name="Queen" p:age="32" p:cars-ref="cars">
</bean>

7.自动装配

Spring IOC容器可以自动装配Bean,需要做的仅仅是在的autowire属性里指定自动装配的模式

自动装配的模式:byType、byName

自动装配的缺点:在Bean配置文件里设置autowire属性进行自动装配将会装配Bena的所有属性,然而之希望装配个别属性

时,autowire属性就不那么灵活了,autowire属性要么根据类型自动装配,要么根据名称自动装配,一般情况下项目项目中

很少使用自动装配,因为和自动装配的好处比起来,清晰明确的配置文档更有说服力。

byType(根据类型自动装配):根据Bean的类型和当前Bean的属性的类型进行自动装配,若IOC容器中有多个与目标

Bean一致的Bean,这种情况下Spring将无法判断那个Bean才适合该属性,所以会导致不能执行自动装配。

byName(根据名称自动装配):根据bean的名字和当前Bean的setter风格的属性名进行自动装配,若有匹配的,

则进行自动装配,否则,不装配,必须将目标Bean的名称和属性设置的完全相同。

constructor(通过构造器自动装配):当Bean中存在多个构造器时,这种自动装配方式将会很复杂,不推荐使用。

8.Bean之间的关系

继承、依赖、抽象

Spring 允许继承 bean 的配置, 被继承的 bean 称为父 bean. 继承这个父 Bean 的 Bean 称为子 Bean

子 Bean 从父 Bean 中继承配置, 包括 Bean 的属性配置子 Bean 也可以覆盖从父 Bean 继承过来的配置,父 Bean

可以作为配置模板, 也可以作为 Bean 实例. 若只想把父 Bean 作为模板, 可以设置 的abstract 属性为 true,

这样 Spring 将不会实例化这个 Bean并不是 元素里的所有属性都会被继承. 比如: autowire, abstract 等.

也可以忽略父 Bean 的 class 属性, 让子 Bean 指定自己的类, 而共享相同的属性配置. 但此时 abstract 必须设为 true

依赖Bean配置,Spring用户允许用户通过的depends-on属性设定Bean的前置依赖Bean,前置依赖的bean会在本Bean

实例化之前创建好,如果前置依赖于多个Bean,则可以通过逗号,空格的方式配置前置Bean的名称

9.Bean的作用域

①singleton:IOC容器默认的作用域是单例的,也就是说IOC容器只会为一个Bean节点创建一个Bean对象,
每次调用getBean()方法只会返回同一个对象。
②prototype:每次向容器获取Bean时,IOC容器都会创建一个新的Bean对象,该对象在创建IOC容器对象时没有创建,
在调用getBean()方法时,才创建。
③web环境作用域:很少使用

10.使用外部属性文件

在配置文件里配置 Bean 时, 有时需要在 Bean 的配置里混入系统部署的细节信息(例如: 文件路径, 数据源配置信息等),

而这些部署细节实际上需要和 Bean 配置相分离Spring 提供了一个 PropertyPlaceholderConfigurer 的 BeanFactory

后置处理器, 这个处理器允许用户将 Bean 配置的部分内容外移到属性文件中. 可以在 Bean 配置文件里使用形式为 var的变量,PropertyPlaceholderConfigurer从属性文件里加载属性,并使用这些属性来替换变量。Spring还允许在属性文件中使用{propName},

以实现属性之间的相互引用。

在Spring2.0的时候,使用外部属性文件:

<bean class="org.springframework.bean.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.propertiess">
</bean>
Spring2.5之后:可通过<context:property-placehoder>元素简化
①:在<beans>中添加context Scheme定义
②:在配置文件中加入如下配置:
<context:property-placeholder location="classpath:db.properties"/>

11.SpEl:Spring表达式语言

①SpEl:是一个支持运行时查询和操作对象图的强大的表达式语言。

②语法类似于 EL:SpEL 使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpEL,SpEL 为 bean 的属性进行动态赋值提供了便利

③SpEL功能:

通过 bean 的 id 对 bean 进行引用

调用方法以及引用对象中的属性

计算表达式的值

正则表达式的匹配

④为属性赋值

整数:<property name="count" value="#{5}"/>
小数:<property name="frequency" value="#{89.7}"/>
科学计数法:<property name="capacity" value="#{1e4}"/>
String可以使用单引号或者双引号作为字符串的定界符号:<property name=“name” value="#{'Chuck'}"/>
或 <property name='name' value='#{"Chuck"}'/>
Boolean:<property name="enabled" value="#{false}"/>

⑤引用Bean、属性和方法

引用其他对象(通过value属性和SpEl配置Bean之间的应用关系)

    <property name="prefix" value="#{prefixGenerator}">
引用其他对象的属性(通过value属性和SpEl配置suffix属性值为另外一个Bean的suffix属性值)
<property name="prefix" value="#{prefixGenerator.suffix}">
调用其他方法,还可以链式操作(通过value属性和SpEl配置suffix属性值为另外一个Bean的方法的返回值 )
<property name="suffix" value="#{sequenceGenerator2.toString()}"/>
方法的连缀
<property name="suffix" value="#{sequenceGenerator2.toString().toUpperCase()}"/>
调用静态方法或静态属性
<property name="initValue" value="#{T(java.lang.Math).PI}"></property>

⑥支持的运算符

+、-、*、/、%、^、+(做字符串连接符)、<、>、==、<=、>=、lt、gt、eg、le、ge、and、or、not、if、else

正则表达式

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

SpringIOC容器可以管理Bean的生命周期,Spring允许在Bean的生命周期的特定点执行定制的任务。

SpringIOC容器对Bean的生命周期进行管理的过程

①通过构造器或工厂方法创建Bean实例
②为Bean的属性设置值和对其他Bean的引用
③调用Bean的初始化方法
④Bean可以使用了
⑤当容器关闭时,调用Bean的销毁方法
在Bean的声明里设置init-method和destory-method属性,为Bean指定初始化和销毁的方法

13.以上配置Bean使用的都是基于XML文件的方式,同时也可以使用基于注解的方式:基于注解配置Bean、基于注解来装配Bean的属性

    在 classpath 中扫描组件:
组件扫描(component scanning): Spring 能够从 classpath 下自动扫描, 侦测和实例化具有特定注解的组件.
特定组件包括:
@Component: 基本注解, 标识了一个受 Spring 管理的组件
@Respository: 标识持久层组件(要么添加到接口上,要么添加到接口的实现类上)
@Service: 标识服务层(业务层)组件
@Controller: 标识表现层组件
对于扫描到的组件, Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写. 也可以在注解中通过 value 属性值标识组件的名称
当在组件类上使用了特定的注解之后, 还需要在 Spring 的配置文件中声明 <context:component-scan> :
base-package 属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类.
当需要扫描多个包时, 可以使用逗号分隔.
如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern 属性过滤特定的类,示例:
<context:component-scan
base-package="com.test.web"
resource-pattern="autowire/*.calss"
<context:include-filter> 子节点表示要包含的目标类
<context:exclude-filter> 子节点表示要排除在外的目标类
<context:component-scan> 下可以拥有若干个 <context:include-filter> 和 <context:exclude-filter> 子节点 @Autowired 注解自动装配具有兼容类型的单个 Bean属性
构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired 注解
默认情况下, 所有使用 @Authwired 注解的属性都需要被设置(注解标识). 当 Spring 找不到匹配的 Bean 装配属性时, 会抛出异常,
若某一属性允许不被设置, 可以设置 @Authwired 注解的 required 属性为 false,默认情况下, 当 IOC 容器里存在多个
类型兼容的 Bean 时,通过类型的自动装配将无法工作. 此时可以在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参
标注 @Qualifiter 已指定注入 Bean 的名称
@Authwired 注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配.
@Authwired 注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean.
@Authwired 注解用在 java.util.Map 上时, 若该 Map 的键值为 String, 那么 Spring 将自动装配与之 Map 值类型
兼容的 Bean, 此时 Bean 的名称作为键值

总结:

    ①使用@Component、@Respository、@Service、@Controller注解类。
②在配置文件中<!-- 指定springIOC容器扫描的包 -->。
<context:component-scan base-package="com.test.spring.beanAnnotation"></context:component-scan>
③使用@Authwired注解为属性字段自动装配Bean,该字段一定要先执行第一步。

问题:当存在类型一样的Bean时,例如实现了同一个接口的两个实现类,则他们的类型一致,如何解决自定装配的问题?

    解决方案一:这是就需要在注解中设置value的属性,该属性值与@Authwired注解标注的字段一样
例如:@Autowired
private UserRepository userRepository;
//UserRepository的实现类上的注解value值为字段的值
@Repository(value="userRepository")
public class UserRepositoryImpl implements UserRepository{}
解决方案二:使用@Qualifier("userJDBCRepository")标注Bean的名称,该注解甚至可以对方法的入参标注
例如:@Qualifier("userJDBCRepository")
private UserRepository userRepository;
该属性会自动装配名称为@Qualifier注解value属性值的Bean

这两种方案一种是在注解字段上做手脚(设置value值),一种是在注解类上做手脚(设置value值)

14.泛型依赖注入

Spring 4.x中可以为子类注入子类对应的泛型类型的成员变量的引用,父类之间建立引用关系

二、Spring案例HelloWorld

1.添加jar包到classpath下

commons-logging.jar

spring-beans.jar

spring-context.jar

spring-core.jar

spring-expression.jar

2.Spring配置文件:一个典型的Spring项目需要创建一个或多个bean配置文件,这些配置文件用于在SpringIOC容器里

配置Bean,Bean配置文件可以放在classpath下,也可以放在其他目录下

Spring(2)—IOC的更多相关文章

  1. Spring的IOC和AOP之深剖

    今天,既然讲到了Spring 的IOC和AOP,我们就必须要知道 Spring主要是两件事: 1.开发Bean:2.配置Bean.对于Spring框架来说,它要做的,就是根据配置文件来创建bean实例 ...

  2. Spring框架IOC容器和AOP解析

    主要分析点: 一.Spring开源框架的简介  二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面向切面编程(AOP)和事务管理配置  一.S ...

  3. Spring总结—— IOC 和 Bean 的总结

    一.Spring 官方文档中给出的 Spring 的整体结构. 二.我自己所理解的 Spring 整体结构图. 三.本次总结 Spring 核心部分 1.从上面图中可以看出,Beans 和 Conte ...

  4. spring的IOC和AOP

     spring的IOC和AOP 1.解释spring的ioc? 几种注入依赖的方式?spring的优点? IOC你就认为他是一个生产和管理bean的容器就行了,原来需要在调用类中new的东西,现在都是 ...

  5. spring容器IOC创建对象<二>

    问题?spring是如何创建对象的?什么时候创建对象?有几种创建方式?测试对象是单例的还是多例的 ?对象的初始化和销毁? 下面的四大模块IOC的内容了!需要深刻理解 SpringIOC定义:把对象的创 ...

  6. Spring中IoC的入门实例

    Spring中IoC的入门实例 Spring的模块化是很强的,各个功能模块都是独立的,我们可以选择的使用.这一章先从Spring的IoC开始.所谓IoC就是一个用XML来定义生成对象的模式,我们看看如 ...

  7. Spring中IOC和AOP的详细解释

    我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入,和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂模式和代理模式. IOC就是典型的工厂模式,通过s ...

  8. Spring的IoC应用

    IoC(Inversion of Control,控制反转) Spring的IoC应用是其框架的最大的特点,通过依赖注入可以大大降低代码之间的耦合度,从而实现代码和功能之间的分离.在代码中可以不直接和 ...

  9. Spring 实践 -IoC

    Spring 实践 标签: Java与设计模式 Spring简介 Spring是分层的JavaSE/EE Full-Stack轻量级开源框架.以IoC(Inverse of Control 控制反转) ...

  10. 挖坟之Spring.NET IOC容器初始化

    因查找ht项目中一个久未解决spring内部异常,翻了一段时间源码.以此文总结springIOC,容器初始化过程. 语言背景是C#.网上有一些基于java的spring源码分析文档,大而乱,乱而不全, ...

随机推荐

  1. centos 6.9安装python 3.6

    .下载源码包在官网按照需要下载到本地 wget https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tgz .解压源码包 tar -xvf Pyt ...

  2. 排查Linux机器是否已被入侵

    来自--马哥Linux运维 1.入侵者可能会删除机器的日志信息 ,可以查看日志信息是否存在后者被清除 [root@zklf-server02 ~]# ll -h /var/log/ total 3.4 ...

  3. Docker数据卷和Docker系统管理(一)

    一. 创建和挂载数据卷 1. 创建数据卷 (1)执行下列命令,创建一个名为my-data的数据卷 [root@c720120 ~]# docker volume create my-data my-d ...

  4. Linux安装Tomcat-Nginx-FastDFS-Redis-Solr-集群——【第二集之新建虚拟机】

    1, 2, 3, 4,(如果选择版本时,发现选项中没有centos,可以选择other linux2.6.x kernel) 5,(虚拟机命名:Centos_用途_IP) 6,(选择Split vir ...

  5. 008 pandas介绍

    一:介绍 1.官网 http://pandas.pydata.org/ 2.说明 Python Data Analysis Library 或 pandas 是基于NumPy 的一种工具,该工具是为了 ...

  6. 页面滚动到指定class样式位置

    var winTop =$(window).scrollTop(); var top = document.getElementsByClassName('is-danger')[0].getBoun ...

  7. VS2017动态链接库(.dll)的生成与使用

    转 https://blog.csdn.net/m0_37170593/article/details/76445972 这里以VS2017为例子,讲解一下动态链接库(.dll)的生成与使用. 一.动 ...

  8. Oracle no TOP, how to get top from order

    On ROWNUM and Limiting Results Our technologist explains how ROWNUM works and how to make it work fo ...

  9. C - Visible Trees HDU - 2841 -莫比乌斯函数-容斥

    C - Visible Trees HDU - 2841 思路 :被挡住的那些点(x , y)肯定是 x 与 y不互质.能够由其他坐标的倍数表示,所以就转化成了求那些点 x,y互质 也就是在 1 - ...

  10. 路由网关---zuul

    Zuul:Zuul 是在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架.Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门. 在微服务盛行的时代,客户端与系统之 ...