IoC的基本认识

Inversion of Control:控制反转,就是将对象的创建权反转交给spring

IoC的好处

传统方式的程序编写,底层的实现切换了,需要修改源代码

使用spring之后,实现类都交给IoC容器中的BeanFactory来管理,通过工厂+反射+配置文件来实现程序的解耦合

<bean id="user" class="com.qf.demo.User">
class BeanFactory{
public static Object getBean(String id) {//id:bean标签的id
Class clazz = Class.forName(className);//className:bean标签的class
return clazz.newInstance();
}
}

IoC和DI

        <bean id="user" class="com.qf.demo.User">
<property name="id" value="1"/>
<property name="name" value="qf"/>
<property name="age" value="18"/>
</bean>

IoC:控制反转,就是将对象的创建权反转给spring

DI:依赖注入,前提必须有IoC的环境,然后Spring管理这个类的时候把这个类依赖的属性注入进来

描述:  
  Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如XML)来指定

Spring的工厂类

  • ApplicationContext是新版本spring的工厂类、BeanFactory是老版本spring的工厂类
  • ApplicationContext继承了BeanFactory接口
  • BeanFactory在调用getBean方法时才会生成类的实例;ApplicationContext在加载配置文件时就会生成类的实例
  • ApplicationContext接口有两个实现类
    • ClassPathXmlApplicationContext:加载类路径下的配置文件
    • FileSystemXmlApplicationContext :加载文件系统下的配置文件

配置spring

applicationContext.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"> <bean id="user" class="com.qf.demo.User">
<property name="id" value="1"/>
<property name="name" value="qf"/>
<property name="age" value="18"/>
</bean> </beans> 

bean配置

bean标签

  1. 标识

    • id:使用了唯一约束;不能使用特殊字符
    • name:未使用唯一约束;可以使用特殊字符,例如 /user
  2. 生命周期
    • init-method:bean被初始化时执行的方法
    • destroy-method:bean被销毁时执行的方法(bean必须是单例创建的才可以进行工厂关闭,多例的情况下无法工厂关闭) 
    • 测试,User类中定义两个方法init和destroy
       package com.qf.demo;
      
       public class User {
      
           private Long id;
      private String name;
      private Integer age; public void setId(Long id) {
      this.id = id;
      }
      public void setName(String name) {
      this.name = name;
      }
      public void setAge(Integer age) {
      this.age = age;
      } @Override
      public String toString() {
      return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
      } public User(Long id, String name, Integer age) {
      super();
      this.id = id;
      this.name = name;
      this.age = age;
      }
      public User() {
      super();
      } public void init() {
      System.out.println("初始化----------");
      }
      public void destroy() {
      System.out.println("销毁----------");
      }
      }

      applicationContext.xml中配置spring管理User对象时配置init属性和destroy属性

      <?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 id="user" class="com.qf.demo.User" init-method="init" destroy-method="destroy">
      <property name="id" value="1"/>
      <property name="name" value="qf"/>
      <property name="age" value="18"/>
      </bean> </beans>

      测试类

      public class TestDemo {
      
      	@Test
      public void test() {
      // ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
      // ApplicationContext类里没有close方法
      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
      User user1 = (User) context.getBean("user");
      System.out.println(user1);
      // User user2 = (User) context.getBean("user");
      // System.out.println(user2);
      context.close();
      }
      }

      console输出结果

      初始化----------
      User [id=1, name=qf, age=18]
      销毁----------  

      注:如果bean中配置scope="prototype",测试会发现destroy不执行,即工厂无法close  

  3. 作用域
    • scope:bean的作用域属性

      • singleton:默认的,spring采用单例模式创建对象
      • prototype:spring采用多例模式创建对象 
      • request:在web项目中使用,spring创建完这个类对象后,将这个对象存入到request中
      • session:在web项目中使用,spring创建完这个类对象后,将这个对象存入到session中
      • globalSession:在web项目中使用,在porlet环境下,spring创建完这个类对象后,这个对象在其子系统中可以使用;没有porlet环境,相当于session
    • 测试1

      • 修改applicationContext.xml的bean配置,配置scope属性

        <bean id="user" class="com.qf.demo.User" scope="prototype">
      • 测试方法
        @Test
        public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user1 = (User) context.getBean("user");
        User user2 = (User) context.getBean("user");
        System.out.println(user2 == user1);
        }
      • console输出结果
        false  
      • 结论:采用多例模式创建对象,两次调用getBean方法创建了两个不同的对象
    • 测试2
      • 在测试1的基础上修改scope属性值为singleton
      • console输出结果
        true
      • 结论:采用单例模式创建对象,两次调用getBean方法创建了两个相同的对象

Spring的bean管理方式

XML方式:适用于任何场景。结构清晰,便于维护

注解方式:如果类不是自己提供的就不能使用(没办法改源码)。开发更加简单方便

XML方式管理Bean

spring的bean的实例化

  1. 无参构造方式实例化bean

    • 自定义bean

      public class TestBean {
      
      	public TestBean() {
      System.out.println("无参构造方式实例化完成");
      }
      }
    • 配置bean 
      <bean id="test" class="com.qf.demo.TestBean"></bean>
    • 测试方法
      @Test
      public void test() {
      ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
      TestBean test = (TestBean) context.getBean("test");
      System.out.println(test);
      }
    • console输出
      无参构造方式实例化完成
      com.qf.demo.TestBean@635c714a
  2. 静态工厂方式实例化bean
    • 创建静态工厂类

      package com.qf.demo;
      
      public class TestBeanFactory {
      public static Bean getBean() {
      System.out.println("静态工厂实例化完成");
      return new Bean();
      }
      }
      class Bean{ }  
    • 配置bean
      <bean id="test" class="com.qf.demo.TestBeanFactory" factory-method="getBean"></bean>
  3. 实例工厂方式实例化bean
    • 创建实例工厂类

      package com.qf.demo;
      
      public class BeanInstance {
      
      	public Bean getInstance() {
      System.out.println("实例工厂方式实例化bean完成");
      return new Bean();
      }
      }
    • 配置bean
      <bean id="instance" class="com.qf.demo.BeanInstance"/>
      <bean id="test" factory-bean="instance" factory-method="getInstance"/>  

属性注入

  1. 构造方法

    • bean类中定义带参数的构造方法

      package com.qf.demo;
      
      public class User {
      private Long id;
      private String name;
      private Integer age;
      private Address address; public User(Long id, String name, Integer age, Address address) {
      super();
      this.id = id;
      this.name = name;
      this.age = age;
      this.address = address;
      }
      public User() {
      super();
      } @Override
      public String toString() {
      return "User [id=" + id + ", name=" + name + ", age=" + age + ", address=" + address + "]";
      }
      }
    • 配置bean
      <bean id="address" class="com.qf.demo.Address"></bean>
      <!-- 构造方法注入属性值,通过index索引注入 -->
      <bean id="user" class="com.qf.demo.User">
      <constructor-arg index="0" value="1"/>
      <constructor-arg index="1" value="wxf"/>
      <constructor-arg index="2" value="24"/>
      <!-- 注入的属性值是另一个bean对象:使用ref属性设置 -->
      <constructor-arg index="3" ref="address"/>
      </bean> <!-- 构造方法注入属性值,通过name参数名称注入 -->
      <bean id="user1" class="com.qf.demo.User">
      <constructor-arg name="id" value="2"/>
      <constructor-arg name="name" value="qf"/>
      <constructor-arg name="age" value="18"/>
      <constructor-arg name="address" ref="address"/>
      </bean>
  2. set方法
    • bean类中定义属性的setter方法

      package com.qf.demo;
      
      public class User {
      private Long id;
      private String name;
      private Integer age;
      private Address address; public void setId(Long id) {
      this.id = id;
      }
      public void setName(String name) {
      this.name = name;
      }
      public void setAge(Integer age) {
      this.age = age;
      }
      public void setAddress(Address address) {
      this.address = address;
      } @Override
      public String toString() {
      return "User [id=" + id + ", name=" + name + ", age=" + age + ", address=" + address + "]";
      }
      }
    • 配置bean
      <bean id="address" class="com.qf.demo.Address"></bean>
      <!-- set方法属性注入 -->
      <bean id="user2" class="com.qf.demo.User">
      <property name="id" value="3"/>
      <property name="name" value="hz"/>
      <property name="age" value="21"/>
      <property name="address" ref="address"/>
      </bean>
  3. p名称空间
    • 用法

      • p名称空间的引入

        • xml的beans标签中添加 xmlns:p="http://www.springframework.org/schema/p" 
      • p名称空间的使用
        • 注入普通属性:p:属性名="属性值"
        • 注入对象属性:p:属性名-ref="属性值"
    • bean类中定义属性的setter方法(类中必须有属性的setter方法,否则抛出NotWritablePropertyException提示缺少属性的setter方法)
    • 配置bean
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:p="http://www.springframework.org/schema/p"
      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 id="address" class="com.qf.demo.Address"/>
      <bean id="user" class="com.qf.demo.User" p:id="4" p:name="wxf" p:age="18" p:address-ref="address"/> </beans>
  4. SpEL注入
    • 基本使用

      • #{SpEL表达式}

        • 字面量表示:#{5}(整数)、#{12.6}(小数)、#{1e3}(科学记数法)、#{'admin'}(字符串)、#{false}(boolean类型)
        • 引用bean表示
          • 引用其它对象:#{address}(address对象是User类的属性)
          • 引用其它对象的属性:#{address.province}(引用address对象的province属性值)
          • 引用其它对象的方法:#{address.getProvice()}、#{address?.getProvice()}(如果address是null,就不调用getProvince()方法了)
    • bean类中定义定义属性的setter方法
    • 配置bean
      <bean id="address" class="com.qf.demo.Address" p:province="AnHui" />
      <bean id="user" class="com.qf.demo.User">
      <property name="id" value="#{5}"/>
      <property name="name" value="#{'qf'}"/>
      <property name="age" value="#{21}"/>
      <property name="address" value="#{address.getInstance()}"/>
      </bean>

注入集合属性

<bean id="collectionBean" class="com.qf.demo.CollectionBean">
<!-- 注入数组 -->
<property name="arr" >
<list>
<value>wxf</value>
<value>admin</value>
<value>qf</value>
</list>
</property> <!-- 注入list -->
<property name="list" >
<list>
<value>asd</value>
<value>zxc</value>
<value>wf</value>
</list>
</property> <!-- 注入set -->
<property name="set" >
<set>
<value>1</value>
<value>2</value>
<value>3</value>
</set>
</property> <!-- 注入数map -->
<property name="map" >
<map>
<entry key="wxf" value="24"></entry>
<entry key="qf" value="18"></entry>
</map>
</property>
</bean>

Spring的分模块开发

  • 加载配置文件时加载多个

    • ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml","applicationContext2.xml");  
  • 在配置文件中引入其它配置文件
    • <import resource="xxx.xml"/>

注解方式管理Bean

IoC注解的基本使用

  1. 引入jar,使用spring注解方式管理bean,需要额外再引入aop的jar包:spring-aop-4.2.4.RELEASE.jar

    • spring-beans-4.2.4.RELEASE.jar
    • spring-context-4.2.4.RELEASE.jar
    • spring-core-4.2.4.RELEASE.jar
    • spring-expression-4.2.4.RELEASE.jar 
    • spring-aop-4.2.4.RELEASE.jar
    • com.springsource.org.apache.commons.logging-1.1.1.jar
    • com.springsource.org.apache.log4j-1.2.15.jar
  2. 引入配置文件
    1. 引入context约束

      <?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">
      </beans>
    2. 开启组件扫描
      <?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">
      <!-- IoC注解开发,配置组件扫描 base-package:哪些包下的类使用注解开发 -->
      <context:component-scan base-package="com.qf.demo2"/>

      </beans>
  3. 创建spring管理的bean类
    • Address.java

      package com.qf.demo2;
      
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.stereotype.Component; @Component("address")
      public class Address {
      @Value("安徽省")
      private String province;
      @Value("合肥市")
      private String city;
      @Override
      public String toString() {
      return "Address [province=" + province + ", city=" + city + "]";
      }
      }
    • User.java
      package com.qf.demo2;
      
      import javax.annotation.Resource;
      
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.stereotype.Component; @Component("user")
      public class User {
      @Value(value="1")
      private Long id;
      @Value(value="qf")
      private String name;
      @Value(value="18")
      private Integer age;
      @Resource(name="address")
      private Address address; @Override
      public String toString() {
      return "User [id=" + id + ", name=" + name + ", age=" + age + ", address=" + address + "]";
      }
      }
  4. 测试
    • 编写测试类

      package com.qf.demo2;
      
      import org.junit.Test;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestDemo {
      @Test
      public void demo() {
      ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
      User user = (User) context.getBean("user");
      System.out.println(user);
      }
      }
    • 测试结果
      User [id=1, name=qf, age=18, address=Address [province=安徽省, city=合肥市]]

IoC注解的详细使用

  1. bean上的注解

    • @Component:针对所有Spring管理的bean都可以使用
    • @Contoller:针对web层
    • @Service:针对service层
    • @Repository:针对dao层
    • 目前和使用@Component没有区别,但是推荐在web层使用@Contoller、service层使用@Service、dao层使用@Repository,结构更加清晰,而且在新版本的spring可能会扩展新的属性
  2. 注解设置属性值
    • 属性有setter方法,需要将属性注入的注解添加在setter方法上

      private String city;
      @Value("合肥市")
      public void setCity(String city) {
      this.city = city;
      }
    • 属性没有setter方法,需要将属性注入的注解添加在属性定义上
      @Value(value="qf")
      private String name;
    • 属性上的注解
      • 普通属性

        • @Value  
      • 对象属性
        • @Autowired:设置对象类型属性的值,按照类型注入
        • @Autowired+@Qualifier("名称"):设置对象类型属性的值,按照名称注入
        • @Resource(name="名称"):设置对象类型属性的值,相当于@Autowired+@Qualifier("名称")
        • @Autowired和@Qualifier是spring框架的注解(org.springframework.beans.factory.annotation.*),@Resource不是spring的注解(javax.annotation.Resource)
  3. bean生命周期的注解
    • @PostConstruct:在bean方法上配置,相当于bean标签的init-method属性(javax.annotation.PostConstruct)
    • @PreDestroy:在bean方法上配置,相当于bean标签的destroy-method属性(javax.annotation.PreDestroy) 
  4. bean作用范围的注解
    • @Scope("可选值")

      • singleton
      • prototype
      • request
      • session
      • globalSession 

XML和注解结合使用

使用XML管理类,使用注解控制属性注入

applicationContext.xml配置文件

  1. 配置组件扫描

    <!-- IoC注解开发,配置组件扫描 base-package:哪些包下的类使用注解开发 -->
    <context:component-scan base-package="com.qf.demo2"/>
    <bean id="user" class="com.qf.demo2.User"></bean>
  2. 不配置组件扫描
    <!--
    激活那些已经在spring容器里注册过的bean,
    让我们可以在没有配置扫描的情况下,使用属性注入的注解@Resource、@Autowired、@Qulifier、@Value
    -->
    <context:annotation-config/>
    <bean id="user" class="com.qf.demo2.User"></bean>

    

二、spring的IoC的更多相关文章

  1. 二 Spring的IOC入门,环境搭建,Spring测试类

    IOC:inversion of Control  控制反转,Spring框架的核心.削减计算机程序的耦合问题,把对象(例如JDBC)的创建权交给Spring. IOC的两种类型: 依赖注入: 依赖查 ...

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

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

  3. 十二、Spring之IOC容器初始化

    Spring之IOC容器初始化 前言 在前面我们分析了最底层的IOC容器BeanFactory,接着简单分析了高级形态的容器ApplicationContext,在ApplicationContext ...

  4. Spring的IOC和AOP之深剖

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

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

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

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

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

  7. Spring重点—— IOC 容器中 Bean 的生命周期

    一.理解 Bean 的生命周期,对学习 Spring 的整个运行流程有极大的帮助. 二.在 IOC 容器中,Bean 的生命周期由 Spring IOC 容器进行管理. 三.在没有添加后置处理器的情况 ...

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

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

  9. Spring的IOC

    引用:http://www.cnblogs.com/xdp-gacl/p/4249939.html 学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念 ...

  10. spring的IOC,DI及案例详解

    一:spring的基本特征 Spring是一个非常活跃的开源框架:它是一个基于Core来架构多层JavaEE系统的框架,它的主要目的是简化企业开发.Spring以一种非侵入式的方式来管理你的代码,Sp ...

随机推荐

  1. vue动态设置Iview的多个Input组件自动获取焦点

    1.html,通过ref=replyBox设置焦点元素,以便后续获取 // 动态设定自动获取焦点按钮 <p class="text-right text-blue fts14 ptb1 ...

  2. vim常用快捷键及操作记录

    1. 安装 sudo apt-get install vim 或者 yum install -y vim-enhanced 2. 具体使用技巧如下 打开文件: 命令/操作 说明 vim + filen ...

  3. c语言开发浏览器插件

    c语言开发浏览器插件 senk????sec???

  4. LOJ3119. 「CTS2019 | CTSC2019」随机立方体 二项式反演

    题目传送门 https://loj.ac/problem/3119 现在 BZOJ 的管理员已经不干活了吗,CTS(C)2019 和 NOI2019 的题目到现在还没与传上去. 果然还是 LOJ 好. ...

  5. 【Mybatis】Mybatis缓存

    mybatis提供了缓存机制减轻数据库压力,提高数据库性能 mybatis的缓存分为两级:一级缓存.二级缓存 一级缓存是SqlSession级别的缓存,缓存的数据只在SqlSession内有效 二级缓 ...

  6. Spring框架之接口实现覆盖(接口功能扩展)

    在日常开发中,存在着这种一种场景,框架对接口A提供了一个种默认的实现AImpl,随着需求的变更,现今AImpl不能满足了功能需要,这时,我们该怎么办? 当然是修改AImpl的实现代码了,但是,如果它是 ...

  7. 左除与右除的区别--MATLAB

    MATLAB 左除与右除的区别 先定义两个矩阵a和矩阵b.如下: /:右除.a/b表示矩阵a乘以矩阵b的逆. \:左除.a\b表示矩阵a的逆乘以b. ./:右除.a./b表示矩阵a中的每个元素除以矩阵 ...

  8. 启动Nginx、查看nginx进程、nginx帮助命令、Nginx平滑重启、Nginx服务器的升级

    1.启动nginx的方式: cd /usr/local/nginx ls

  9. linux nfs文件共享

    ◆一.概念   NFS是网络文件系统(Network File System)的简称,是分布式计算机系统的一个组成部分,可实现在异构网络上共享和装配远程文件系统.   NFS由SUN公司开发,目前已成 ...

  10. vue 点击其他地方隐藏dom

    document.addEventListener('click', function (e) { if (document.getElementsByClassName('keywordContai ...