二、Spring之IoC

1. IoC与DI

(1) IoC

控制反转( IoC, Inversion of Control) , 是一个概念, 是一种思想。 控制反转就是对对象控制权的转移, 从程序代码本身反转到了外部容器。 把对象的创建、 初始化、销毁等工作交给spring容器来做。 由spring容器控制对象的生命周期。

DI

依赖注入: Dependency Injection。 依赖注入DI是指程序运行过程中, 若需要调用另

一个对象协助时, 无须在代码中创建被调用者, 而是依赖于外部容器, 由外部容器创

建后传递给程序。

依赖注入是目 前最优秀的解耦方式。 依赖注入让Spring的Bean之间以配置文件的方式

组织在一起, 而不是以硬编码的方式耦合在一起的。

IoC与DI的关系

IoC是一个概念, 是一种思想, 其实现方式多种多样。 当前比较流行的实现方式之一

是DI。

2. 第一个IoC程序

(1) 导入jar包( 基本4个)

spring-beans-4.3.16.RELEASE.jar

spring-context-4.3.16.RELEASE.jar

spring-core-4.3.16.RELEASE.jar

spring-expression-4.3.16.RELEASE.jar

再放入两个日志包:

com.springsource.org.apache.commons.logging-1.1.1.jar

com.springsource.org.apache.log4j-1.2.15.jar

(2) 创建spring配置文件

1) 创建applicationContext.xml

2) spring-framework-4.3.16.RELEASE/docs/spring-framework-reference/html/

xsd-configuration.html 中找到配置文件头信息(the beans schema)

<?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的定义:以下配置相当于SomeService service = new SomeServiceImpl(); -->

<bean id="someServiceImpl" class="com.mypack.service.impl.SomeServiceImpl"></bean>

</beans>

3) 复制本地文件 D:\eclipse_mars2\xsd\spring-beans-4.3.xsd 到 eclipse目录

复制http://www.springframework.org/schema/beans/

spring-beans.xsd 到XML catalog中 key

(3) Bean的定义与注册

<bean id="someServiceImpl" class="com.mypack.service.impl.

SomeServiceImpl"></bean>

(4) 从spring容器中获取Bean

ApplicationContext ac = new ClassPathXmlApplicationContext

("applicationContext.xml"); //通过ClassPathXmlApplicationContext这个实现类创建容器对象

SomeService service = ac.getBean("someServiceImpl", SomeService.class);

service.doSome();

(5) 另一种方法:通过BeanFactory创建

BeanFactory bf = new XmlBeanFactory(new ClassPathResource

("applicationContext.xml"));

SomeService service = bf.getBean("someServiceImpl", SomeService.class);

service.doSome();

 

3. ApplicationContext容器与BeanFactory容器的区别

(1) ApplicationContext

容器初始化时,所有的容器中的bean创建完毕,效率高但占用内存较多。

(2) BeanFactory当调用getBean获取相应对象时,才创建对象。

一开始不创建对象,不占用内存,但效率低。

4. Bean的装配

Bean的装配, 即Bean对象的创建。

(1)  默认装配方式(构造方式)

通过无参构造器创建对象,如上所示。

(2) 动态工厂创建Bean对象

先实例工厂方式创建bean对象

public SomeService getSomeService(){

SomeService someServiceImpl = new SomeServiceImpl();

return someServiceImpl;

}

 

然后在xml中注册工厂,从工厂中获取someServiceImpl的bean对象

<bean id="serviceFactory" class="com.mypack.factory.ServiceFactory"></bean>

<bean id="someServiceImpl" factory-bean="serviceFactory" factory-method="getSomeService"></bean>

 

(3) 静态工厂创建Bean对象

在ServiceFactory方法中创建静态方法

public class ServiceFactory {

public static SomeService getSomeService(){

SomeService someServiceImpl = new SomeServiceImpl();

return someServiceImpl;

}

}

 

xml文件中获取someServiceImpl的bean对象,直接通过类名.的方式调用

<bean id="someServiceImpl" class="com.mypack.factory.ServiceFactory" factory-method="getSomeService"></bean>

5. Bean的作用域

(1) 单态模式

SomeService service1 = ac.getBean("someServiceImpl", SomeService.class);

SomeService service2 = ac.getBean("someServiceImpl", SomeService.class);

System.out.println(service1==service2);

 

结果为true,容器初始化的时候,所有bean对象已经创建完毕。我们从容器中获取的对象拿到的都是相同对象。

(2) 原型模式

xml文件中,scope属性改为prototype,可变为原型模式(默认是单态模式singleto)

<bean id="someServiceImpl" class=

"com.mypack.service.impl.SomeServiceImpl" scope="prototype"></bean>

6. 基于XML的DI

所谓注入,可理解为对象的属性赋值

(1) 设值注入

1) 简单数据类型和引用数据类型注入

通过property标签进行赋值,简单数据类型(基本类型和字符串)使用value属性进行注入,引用类型用ref进行注入。

<bean id="star" class="com.mypack.pojo.Star">

<property name="name" value="贝克汉姆"></property>

<property name="age" value="39"></property>

<property name="partner" ref="partner"></property>

</bean>

 

<bean id="partner" class="com.mypack.pojo.Partner">

<property name="name" value="维多利亚"></property>

</bean>

2) 集合属性注入(array、set、list、map、properties)

<bean id="partner1" class="com.mypack.pojo.Partner">

<property name="name" value="维多利亚"></property>

</bean>

<bean id="partner2" class="com.mypack.pojo.Partner">

<property name="name" value="布兰妮"></property>

</bean>

<bean id="someService" class="com.mypack.service.SomeService">

<property name="myArray">

<!--字符串数组通过array子标签,用value属性注入-->

<array>

<value>北京</value>

<value>上海</value>

</array>

</property>

<property name="mySet">

<!--set集合通过set子标签,泛型是partner,用ref属性注入-->

<set>

<ref bean="partner1"/>

<ref bean="partner2"/>

</set>

</property>

<property name="myList">

<!--list集合通过list子标签,泛型是字符串,用value属性注入-->

<list>

<value></value>

<value></value>

</list>

</property>

<!--map集合通过map子标签,用entry属性为键值对赋值-->

<property name="myMap">

<map>

<entry key="qq" value="123456"></entry>

<entry key="mobile" value="13300000"></entry>

</map>

</property>

<!--property属性集通过props子标签,用key属性,值放在标签体里面-->

<property name="myProps">

<props>

<prop key="兴趣">足球</prop>

<prop key="爱好">下棋</prop>

</props>

</property>

</bean>

3) 域属性自动注入

① byName

byName方式域属性自动注入:要求注入的bean的id必须和被注入的bean象的属性名一致。使用autowire属性,设为byName。

<bean id="star" class="com.mypack.pojo.Star" autowire="byName">

<property name="name" value="贝克汉姆"></property>

<property name="age" value="39"></property>

</bean>

id="partner"和star类中相应的属性名要一致

<bean id="partner" class="com.mypack.pojo.Partner">

<property name="name" value="维多利亚"></property>

</bean>

 

    

② byType方式域属性自动注入:spring配置文件中查询与属性类型一致的bean并进行注入,autowire属性,设为byType。

<bean id="star" class="com.mypack.pojo.Star" autowire="byType">

<property name="name" value="贝克汉姆"></property>

<property name="age" value="39"></property>

</bean>

4) 局部配置方式和全局配置方式
① 局部配置方式:在bean便签当中,使用autowir属性进行注入。

代码如上所示。

②全局配置方式:配置文件中所有的bean都使用该种配置方式。

在beans标签下加入default-autowire="byType"(或byName),把每个bean标签中的autowire属性去掉。

5) 空字符串或null的注入

去掉原来的数值,加入<value>标签,可注入空字符串。

<property name="name"><value/></property>

加入<null/>标签,可注入空字符串。

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

(2) 构造注入

1) 使用<constructor-arg>标签的name属性注入

<bean id="star" class="com.mypack.pojo.Star">

<constructor-arg name="name" value="郭靖"></constructor-arg>

<constructor-arg name="age" value="25"></constructor-arg>

<constructor-arg name="partner" ref="partner"></constructor-arg>

</bean>

2) 使用<constructor-arg>标签的index属性(索引号)注入

<bean id="star" class="com.mypack.pojo.Star">

<constructor-arg index="0" value="郭靖"></constructor-arg>

<constructor-arg index="1" value="25"></constructor-arg>

<constructor-arg index="2" ref="partner"></constructor-arg>

</bean>

3) 对构造器中对应的属性值进行注入

<bean id="star" class="com.mypack.pojo.Star">

<constructor-arg value="郭靖"></constructor-arg>

<constructor-arg value="25"></constructor-arg>

<constructor-arg ref="partner"></constructor-arg>

</bean>

7. 基于注解的DI

1) 环境搭建:导入aop包、添加context约束头信息(组件扫描器)

导入包spring-aop-4.3.16.RELEASE

到 spring-framework-4.3.16.RELEASE/docs/spring-framework-reference/htmlsingle/

index.html 中查找context schema,复制这一段到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"

xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="

        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->

</beans>

添加组件扫描器:

<context:component-scan base-package="com.mypack.pojo"></context:component-scan>

类定义前加上@Component,表示当前类交给Spring容器管理。为类成员注入值用@Value,对象属性用@Autowired注入。

@Component("myPartner")

public class Partner {

@Value("张三")

private String name;

@Override

public String toString() {

return "Partner [name=" + name + "]";

}

}

@Component

@Scope("prototype")

public class Star {

//简单数据类型通过@Value注入

@Value("李四")

private String name;

@Value("23")

private int age;

//引用数据类型通过@Autowired注入;默认情况下是byType方式注入;如果使用byName方式自动注入,

//需要与@Qualifier联合使用

/*

@Autowired

@Qualifier("myPartner")

*/

//引用数据类型通过@Resource也可以实现注入;默认情况下是byName方式注入,

//只有找不到与名称匹配的bean的时候才会按照类型来进行注入

@Resource

private Partner partner;

@Override

public String toString() {

return "Star [name=" + name + ", age=" + age + ", partner=" + partner + "]";

}

}

2) 常用注解:

@Component:当前类作为一个组件,交给容器进行管理

与@Component具有相同功能的还有另外3个注解

* @Repository:该注解添加在Dao实现类上

* @Service:该注解添加在Service实现类上

* @Controller:该注解添加在Controller类上

@Scope:bean作用域相关注解,指定对象的生命周期,singleto(默认),prototype,request,session,global session

@Value:对简单数据类型的依赖注入

@Resource:预属性注解(JDK),用于给引用注入容器的对象,默认byType

@Autowired:预属性注解(Spring),用于给引用注入容器的对象,默认byName

3.1.2 Spring之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. [python] ThreadPoolExecutor线程池 python 线程池

    初识 Python中已经有了threading模块,为什么还需要线程池呢,线程池又是什么东西呢?在介绍线程同步的信号量机制的时候,举得例子是爬虫的例子,需要控制同时爬取的线程数,例子中创建了20个线程 ...

  2. ShiftRows方法简介

    ShiftRows 是HSSFSheet工作薄的方法 ShiftRows(int startRow,int endRow,int n)参数介绍:startRow:开始行endRow:末尾行n:移动n行 ...

  3. 【iCore4 双核心板_uC/OS-II】例程八:消息邮箱

    一.实验说明: 消息邮箱是uC/OS-II中的另一种通信机制,可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量.通常该指针指向一个包含了“消息”的特定数据结构.   二.实验截图:   ...

  4. 最简单的设计模式——单例模式的演进和推荐写法(Java 版)

    前言 如下是之前总结的 C++ 版的:软件开发常用设计模式—单例模式总结(c++版),对比发现 Java 实现的单例模式和 C++ 的在线程安全上还是有些区别的. 概念不多说,没意思,我自己总结就是: ...

  5. 设计模式——proxy代理模式

    目录 概述 定义 角色 为什么会有代理模式? 应用场景 示例 静态代理 例子 动态代理 JDK中生成代理对象的API 代码示例: 代码示例2 Cglib代理 代码示例 AOP(AspectOrient ...

  6. js和css实现手机横竖屏预览思路整理

    实现效果,如上图. 首先,实现手机页面在PC端预览, 则先在网上找到一个手机的背景图片,算好大概内间距,用来放预览的页面,我这里是给手机预览页面的尺寸按iphone5的尺寸来的: 一个手机页面在这里预 ...

  7. SpringBoot------整合MyBatis

    1.添加pom.xml需要的依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="htt ...

  8. SQL查询无限层级结构的所有下级,所有上级

    无限层级结构的table1表,Id(主键),ParentId(父级id)查询某个Id的所有下级或所有上级,使用WITH AS,UNION ALL 查询 1.查询Id为1所有的下级 WITH T AS( ...

  9. Page Lifecycle API

    今天的现代浏览器有时在系统资源受限的情境下会暂停页面或完全放弃执行它.将来,浏览器会主动执行此操作,因此它们会消耗更少的电量和内存.在Chrome 68中提供的Page Lifecycle API提供 ...

  10. [原][openstack-pike][controller node][issue-3][horizon] dashboard show internal error 500 Cannot serve directory /var/www/html

    问题点: 安装完pike后发现只能使用 ip:80 登录到http的主页面 不能使用 http://controller_ip:80/dashboard 登录openstack登录页面.如下图 重启h ...