spring5(6) ---Ioc和DI

目录

一.基础

二.Spring Ioc管理bean的原理:

三.getBean方法的三种签名

四.创建bean时机

五.bean实例化的方式:

六.bean作用域:

七.bean初始化和销毁

八.bean实例化过程


一.基础

正控:若调用者需要使用某个对象,其自身就得负责该对象及该对象所依赖对象的创建和组装

反控:调用得只管理从Spring容器中获取需要使用的对象,不关心对象的创建过程,也不关心该对象依赖对象的创建及依赖关系的组装,也就是把创建对象的控制权反转给了Spring框架。

Ioc:Inversion of Control(控制反转/反转控制),这不是什么新技术,而是一种设计思想,好比如MVC,其本意是将原本在程序中手动创建对象的控制,交由Spring框架来管理

DI:Dependency Injecttion(依赖注入)从字面上分析,Ioc指将对象的创建权反转给了Spring容器;即指Spring创建对象的过程中,将对象依赖属性(常量,对象,集合)通过配置设值给该对象

例子:

实体类:

  1. public class HelloWorld{

  2. private String name;

  3. private int age;

  4. ...相应的get和set方法

  5. }

XML配置:

  1. <bean id="helloWorld" class="com.bigfong.HelloWorld">

  2. <property name="name" value="bigfong">对应HelloWorld中的setName方法

  3. <property name="age" value="20">对应HelloWorld中的setAge方法

  4. </bean>

测试代码:

  1. HelloWorld helloWorld = null;

  2. //加载Spring配置文件applicationContext.xml

  3. Resource resource = new ClassPathResource("applicationContext.xml");

  4. //创建Spring容器对象

  5. BeanFactory factory = new XmlBeanFactory(resource);

  6. //从Spring容器中获取制定名为helloWorld的bean

  7. helloWorld = (HelloWorld)factory.getBean("helloWorld");//xml对应bean配置的id值

  8. helloWorld.sayHello();

BeanFactory是Spring最古老的接口,表示Spring Ioc容器------生产bean对象的工厂,负责配置,创建和管理bean,被Spring Ioc容器管理的对象称之为bean

Spring Ioc容器如何得知哪些是它管理的对象:

此时需要配置文件,Spring Ioc容器通过读取配置文件中的配置元数据,通过元数据对应用中的各个对象进行实例化及装配

二.Spring Ioc管理bean的原理:

1.通过Resource对象加载配置文件

2.解析配置文件,得到指定名称的bean

3.解析bean元素,id作为bean的名字,class用于反射得到bean的实例;(此时,bean类必须存在一个无参构造器【和访问权限无关】);

4.调用getBean方法的时候,从容器中返回对象实例

结论:就是把代码从java文件中转移到了XML中

模拟Spring Ioc容器操作

  1. HelloWorld helloWorld = null;

  2. String className = "com.bigfong.HelloWorld";

  3. Class clz = Class.forName(className);

  4. Constructor con = clz.getDeclaredConstructor();

  5. con.setAccessible(true);

  6. helloWorld = (HelloWorld)con.newInstance();

  7. BeanInfo beanInfo = Introspector.getBeanInfo(helloWorld.getClass());

  8. PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();

  9. for(PropertyDescriptor pd:pds){

  10. String propertyName = pd.getName();

  11. Method setterMethod = pd.getWriteMethod();

  12. if("name".equals(propertyName)){

  13. setterMethod.invoke(helloWorld,"bigfong");

  14. }elseif("age".equals(propertyName)){

  15. setterMethod.invoke(helloWorld,20);

  16. }

  17. }

  18. helloWorld.sayHello();

三.getBean方法的三种签名

1.按照bean的名字拿bean

helloWorld = (HelloWorld)factory.getBean("helloWorld");

2.按照类型拿bean,要求在Spring中只配置一个这种类型的实例

helloWorld = (HelloWorld)factory.getBean(HelloWorld.class);

3.按照名字和类型拿bean(推荐)

helloWorld = (HelloWorld)factory.getBean("helloWorld",HelloWorld.class);

四.创建bean时机

1.使用BeanFactory

  1. Resource resource = new ClassPathResource("com/bigfong/container/container.xml");//在这里不需要添加"classpath:"开头

  2. BeanFactory factory = new XMLBeanFactory(resource);

  3. HelloWorld helloWorld = factory.getBean("helloWorld",HelloWorld.class);

BeanFactory有延迟初始化的特点,在创建Spring容器的时候,不会立马去创建容器中管理的Bean对象,而是要等到从容器中去获取对象的时候,才去创建对象。

2.使用ApplicationContext  (Web应用建议)

  1. ApplicationContext ctx = new ClassPathXmlApplicationContext("com/bigfong/container/container.xml");//在这里不需要添加"classpath:"开头

  2. HelloWorld helloWorld = ctx .getBean("helloWorld",HelloWorld.class);

在创建Spring容器的时候,就会把容器中管理的bean立马初始化,而不会等到获取bean的时候才去初始化.

五.bean实例化的方式

1.构造实例化(无参数构造器),最标准,使用最多

  1. <bean id="cat1" class="com.bigfong.createbean.Cat1"/>

  2. com.bigfong.createbean.Cat1类有无参构造器

  3. 根当于 Cat1 cat2 = new Cat1();

2.静态工厂方法实例化:解决系统遗留问题

  1. <bean id="cat2" class="com.bigfong.createbean.Cat2Factory" factory-method="createInstance"/>

  2. 其中com.bigfong.createbean.Cat2Factory

  3. public static Cat2 createInstance(){

  4.    Cat2 cat2 = new Cat2();

  5.    return cat2;

  6. }

  7. 相当于 Cat2 cat2 = Cat2Factory.createInstance();

3.实例工厂实例化:解决系统遗留问题

  1. <bean id="cat3Factory" class="com.bigfong.createbean.Cat3Factory"/>

  2. <bean id="cat3" factory-bean="cat3Factory" factory-method="createInstance"/>

  3. 其中com.bigfong.createbean.Cat3Factory

  4. public Cat3 createInstance(){

  5.    Cat2 cat2 = new Cat2();

  6.    return cat2;

  7. }

  8. 相当于 Cat3 cat3 = new Cat3Factory().createInstance();

4.实现BeanFactory接口实例化:实例工厂变种,如集成MyBatis框架使用:

org.mybatis.spring.SqlSessionFactoryBean

  1. <bean id="cat4" class="com.bigfong.createbean.Cat4Factory"/>

  2. 其中com.bigfong.createbean.Cat4Factory

  3. public class Cat4Factory implements FactoryBean<Cat4>{

  4. //实例工厂方法

  5. public Cat4 getObject() throws Exception{

  6. Cat4 cat4 = new Cat4();

  7.     return cat4;

  8. }

  9. public Class<?> getObjectType(){

  10. return Cat4.class;

  11. }

  12. }

  13. 相当于 Cat4 cat4 = new Cat4Factory().getObject();

六.bean作用域:

在spring容器中指创建的Bean对象相对于其他Bean对象的请求可见范围

<bean id="" class="" scope="作用域"/>

1.singleton:单例,在spring Ioc容器中仅存在一个Bean实例(默认的scope)

2.prototype:多例,每次从容器中调用Bean时,都返回一个新的实例,即每次调用 getBean()时,相当于new XxxBean();不会在容器启动的时候创建对像

3.request:用于web开发,将Bean放入request范围,request.setAttribute("xxx"),在同一个request获得同一个bean

4.session:用于web,将Bean放入Session范围,同一个Session获得同一个Bean

5.globalSession:一般用于Porlet应用环境,分布式系统存在全局session概念(单点登录),如果不是porlet环境,globalSession等同于Session

6.application:

7.websocket:

spring5开始出现:websocket,globalSession作废

在开发中主要使用:singletom,prototype

总结:对于Struts1中的Action使用request,Struts2中的Action使用prototype类型,其他使用singleton

七.bean初始化和销毁

<bean id="user" class="com.bigfong.user" scope="prototype" init-method="open" destroy-method="close"/>

init-method:定义初始化方法,在构造器执行之后立马执行

destroy-method:定义销毁之前的方法,在销毁之前调用

测试:

  1. ApplicationContext ctx = new ClassPathXmlApplicationContext("com/bigfong/context.xml");

  2. User user = ctx.getBean("user",User.class);

此时因为没有正常关闭spring容器,所以不会执行释放资源的方法,可以使用@Cleanup注解

  1. @Cleanup

  2. ApplicationContext ctx = new ClassPathXmlApplicationContext("com/bigfong/context.xml");

  3. User user = ctx.getBean("user",User.class);

最好的方式是把spring线程作为JVM的子线程,ctx.registerShutdownHook();

  1. ApplicationContext ctx = new ClassPathXmlApplicationContext("com/bigfong/context.xml");

  2. User user = ctx.getBean("user",User.class);

  3. ctx.registerShutdownHook();

原理:如果bean的scope="prototype",容器只负责创建和初始化,它并不会被spring容器管理,交给用户自己调用 。

八.bean实例化过程

bean的完整生命周期经历了各种方法,这些方法可以划分为改下几类:

1.Bean自身的方法: 包括Bean本身调用 的方法和通过配置文件中<bean>的init-method和destrory-method指定的方法

2.Bean级生命周期接口方法: 包括了BeanNameAware、BeanFactoryAware、InitializingBean和DisposibleBean这些接口方法

3.容器级生命周期接口方法:包括InstantiationAwareBeanPostProcessor和BeanPostProcessor这两个接口实现类,一般称它们的实现类为“后处理器”

4.工厂后处理器接口方法:包括AspectJWeavingEnabler,ConfigurationClassPostProcessor,CustomAutowireConfigurer等非常有用的工厂后处理器接口方法。工厂后处理器也是容器级的。在应用上下文装配配置文件后立即调用。

DI基础

注入方式:1.setter注入,2.构造器注入

注入的值类型:

1.简单类型: value元素

2.对象: ref元素

3.集合:对应集合类型元素<set> <list>

通过XML装配

  1.XML自动装配(不推荐)

<bean id="somebean" class="com.bigfong.SomeBean" autowire="byType">

autowire:让spring按照一定的规则方式自己去找合适的对像,并完成DI操作

default:不要自动注入,缺省default列示no

no:不要自动注入

byName:按照名字注入(近照属性名字在srping中找bean)factory.getBean(beanName)

byType:按照依赖对像的类型注入(factory.getBean(Class requiredType))

constructor:按照对象的构造器上面的参数类型注入

  2.setter注入

  1. <bean id="cat1" class="com.bigfong.Cat">

  2. <bean id="user" class="com.bigfong.User">

  3. <property name="username" value="bigfong"/>//常量

  4. <property name="cat" ref="cat1"/>//对象

  5. <property name="set">集合:set

  6. <set>

  7. <value>set1</value>

  8. <value>set2</value>

  9. <value>set3</value>

  10. </set>

  11. </property>

  12. <property name="list">集合:list

  13. <list>

  14. <value>list1</value>

  15. <value>list2</value>

  16. <value>list3</value>

  17. </list>

  18. </property>

  19. <property name="array">集合:Array

  20. <array>

  21. <value>array1</value>

  22. <value>array2</value>

  23. <value>array3</value>

  24. </array>

  25. </property>

  26. <property name="map">集合:Map

  27. <map>

  28. <entry key="key1" value="value1"/>

  29. <entry key="key2" value="value2"/>

  30. <entry key="key3" value="value3"/>

  31. </map>

  32. </property>

  33. <property name="prop">集合:Properties类型 方式一

  34. <props>

  35. <prop key="key1" ">value1</prop>

  36. <prop key="key2" ">value2</prop>

  37. <prop key="key3" ">value3</prop>

  38. </props>

  39. </property>

  40. <property name="prop">集合:Properties类型 方式二

  41. <value>

  42. p1=v1

  43. p2=v2

  44. p3=v3

  45. </props>

  46. </property>

  47. </bean>

  3.构造器注入

  1. <bean id="cat1" class="com.bigfong.Cat">

  2. <bean id="user" class="com.bigfong.User">

  3. <constructor-arg name="username" value="bigfong">

  4. <constructor-arg name="age" value="20">

  5. <constructor-arg name="weight">

  6. <null/>

  7. </constructor-arg>

  8. <constructor-arg name="cat" ref="cat1"/>

  9. <constructor-arg bane="set">集合:set

  10. <set>

  11. <value>set1</value>

  12. <value>set2</value>

  13. <value>set3</value>

  14. </set>

  15. </constructor>

  16. </bean>

3.bean元素继承

  1. //多个bean工内配置的抽取

  2. <bean id="base" abstract="true">

  3. <property name="username" vaue="bigfong"/>

  4. <property name="age" vaue="20"/>

  5. </bean>

  6. <bean id="somebean" class="com.bigfong.user" parent="base">

  7. <property name="weight" value="50">

  8. </bean>

  9. <bean id="somebean2" class="com.bigfong.user" parent="base">

  10. <property name="color" value="yellow">

  11. </bean>

  4.property place holder

  方法一:数据库连接池

  1. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">

  2. <property name="driverClassName" value="com.mysql.jdbc.Driver"/>

  3. <property name="url" value="jdbc:mysql://localhost:3306/springDemo"/>

  4. <property name="username" value="root"/>

  5. <property name="password" value="admin"/>

  6. <property name="initialSize" value="2"/>

  7. </bean>

  方法二:使用property place holder  

db.properties

  1. jdbc.driverClassName=com.mysql.jdbc.Driver

  2. jdbc.url=jdbc:mysql://localhost:3306/springdemo

  3. jdbc.username=root

  4. jdbc.password=admin

  5. jdbc.initialSize=2

App-context.xml

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  3. xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"

  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

  5. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

  6. <!-- 从classpath的根路径去加载db.properties文件 -->

  7. <context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER" />

  8. <!-- 配置一个druid的连接池 -->

  9. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">

  10. <property name="driverClassName" value="${jdbc.driverClassName}" />

  11. <property name="url" value="${jdbc.url}" />

  12. <property name="username" value="${jdbc.username}" />

  13. <property name="password" value="${jdbc.password}" />

  14. <property name="initialSize" value="${jdbc.initialSize}" />

  15. </bean>

  16. </beans>

spring5(6) ---Ioc和DI相关推荐

  1. 详细介绍 IOC 和 DI

    点击关注公众号,Java干货及时送达 学习过 Spring 框架的人一定都会听过 Spring 的 IoC (控制反转) .DI (依赖注入)这两个概念,对于初学 Spring 的人来说,总觉得 Io ...

  2. 这可能是对 IOC 和 DI 解释的最清楚的一篇文章了!

    作者 | fuzhongmin05 来源 | http://fuzhongmin05blog.csdn.net/fuzhongmin05/article/details/55802816 学习过spr ...

  3. 彻底理解Spring IOC和DI

    目录 前言 1. 分享Iteye的开涛对Ioc的精彩讲解 1.1 IoC是什么 1.2 IoC能做什么 1.3 IoC和DI 2. 分享Bromon的blog上对IoC与DI浅显易懂的讲解 2.1 I ...

  4. 深入理解DIP、IoC、DI以及IoC容器

    对于大部分小菜来说,当听到大牛们高谈DIP.IoC.DI以及IoC容器等名词时,有没有瞬间石化的感觉?其实,这些"高大上"的名词,理解起来也并不是那么的难,关键在于入门.只要我们入 ...

  5. spring IOC和DI

    spring IOC and DI 1.IOC和DI的区别: IOC:对象的管理权由spring容器掌握(管理权限包括:对象的创建时间点.创建方式以及对象属性的管理): DI:spring操作对象属性 ...

  6. java元婴期(18)----java进阶(spring(2)----DI(依赖注入)基于注解的IOC与DI配置properties)

    1.依赖注入的概念 依赖注入:Dependency Injection.它是spring框架核心ioc的具体实现. 我们的程序在编写时,通过控制反转,把对象的创建交给了spring,但是代码中不可能出 ...

  7. 互相引用 spring_巧夺天工,这样理解Spring的IOC、DI下来,真的很清晰了

    前言 你可能会有如下问题: 想看Spring源码,但是不知道应当如何入手去看,对整个Bean的流程没有概念,碰到相关问题也没有头绪如何下手 看过几遍源码,没办法彻底理解,没什么感觉,没过一阵子又忘了本 ...

  8. Spring-学习笔记03【Spring的IOC和DI】

    Java后端 学习路线 笔记汇总表[黑马程序员] Spring-学习笔记01[Spring框架简介][day01] Spring-学习笔记02[程序间耦合] Spring-学习笔记03[Spring的 ...

  9. IOC和DI 控制反转和依赖注入

    首先要分享的是Iteye的开涛这位技术牛人对Spring框架的IOC的理解,写得非常通俗易懂,以下内容全部来自原文,原文地址:http://jinnianshilongnian.iteye.com/b ...

最新文章

  1. 职场,18个细节决定成败[转载]
  2. 一起走进自然语言处理的世界
  3. c语言如何跟进自定义赋值,用最简单的C语言编写自定义函数之数字后移
  4. C#实现winform仿div+css半透明遮罩效果
  5. python分割数字_对python数据切割归并算法的实例讲解
  6. 2_5 BridgeMode.cpp 桥接模式
  7. c语言判断闰年_大一C语言错题
  8. fedora下软件安装
  9. java timmer模式配置_使用java配置定时任务的几种配置方式及示例
  10. python绘图之散点图
  11. 花生壳+FileZilla搭建公网FTP服务器
  12. 谈谈软件人的职业规划
  13. ccxprocess用不用自启_你电脑上开机自启的软件都有哪些?
  14. 在linux下如何显示隐藏文件
  15. python语言是网络编程语言吗_三大主流编程语言Python为啥这么牛?
  16. 【T+】删除/取消畅捷通T+软件登录账套后的“查看认证”按钮
  17. 中国羊奶皂市场趋势报告、技术动态创新及市场预测
  18. 关于背单词的一点个人体会
  19. Python中的蛇和梯子(单人游戏)
  20. 汇川H5U PLC通过 EtherCAT总线控制伺服回原

热门文章

  1. php判断日期文章变红,DeDecms如何实现当天发表的文章日期以红色显示
  2. STC51-1602、12232、12864液晶
  3. D/A转换器(华师)
  4. java回合制武侠手游_‎App Store 上的“群侠传-怀旧开放武侠RPG回合制手游”
  5. JAVA8的双重循环怎么优化_Java8处理List的双层循环问题代码实例
  6. php报错提醒,php报错问题
  7. 管程理解及用管程实现生产者消费者问题
  8. mysql处理重复数据
  9. Atom打造 c/c++编译环境(忙了一个上午)
  10. Eclipse如何导入第三方jar包