Spring中IOC容器

一、IOC容器

IOC底层原理

IOC的概念和原理

1.什么是IOC?

(1)控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理

(2)使用IOC目的:为了降低耦合度

2.IOC底层原理

(1)xml解析、工厂模式、反射

IOC 的操作

第一步 xml配置文件,配置创建对象

<bean id="dao" class="com.lp.UserDao"></bean>

第二步 有service类和dao类,创建工厂类

Spring中IOC容器

 

IOC接口(BeanFactory)

1.IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

2.Spring提供IOC容器实现两种方式:(两个接口)

(1)BeanFactory:IOC容器的基本使用,是Spring内部的使用接口,不提供开发人员进行使用

特点:加载配置文件的时候不会创建对象,在获取(使用)对象的时候才会创建对象

(2)ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用

特点:加载配置文件的时候就会吧在配置文件对象进行创建

3.ApplicationContext的主要实现类

IOC操作Bean管理(基于XML)

什么是Bean管理?

(1)Spring 创建对象

(2)Spring注入属性

1.基于xml方式创建对象

<bean id="dao" class="com.lp.UserDao"></bean>

(1)属性介绍:

id属性:唯一标识

class属性:类全路径(包类路径)

(2)创建对象时候,默认是执行无参数构造方法

2.基于xml方式注入属性:

(1)DI:依赖注入,就是注入属性

第一种注入方式:使用set方法注入

①创建类,定义属性和对一个的set方法

②在spring配置文件配置对象创建,配置属性注入

使用property完成属性注入:name:类里面属性名称

value:向属性注入的值

 <!--set方法注入属性-->
      <bean id="book" class="com.lp.springDemo1.book.Book">
          <property name="bname" value="《格林童话》"></property>
          <property name="bauthor" value="安徒生"></property>
      </bean>

第二种注入方式:使用有参构造注入

<!--构造方法注入属性-->
      <bean id="book" class="com.lp.springDemo1.book.Book">
          <constructor-arg index="0" value="《西游记》"></constructor-arg>
          <constructor-arg index="1" value="吴承恩"></constructor-arg>
      </bean>

注意:xml注入其他类型的属性

1.字面量

(1)null值

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

(2)属性值包含特殊符号

①把<>进行转义&lt,&rt

②把带特殊符号的内容写到CDATA中,如:

<property name="bauthor">
      <value><![CDATA[《水浒传》]]></value>
  </property>

2.注入属性——外部bean

(1)创建两个类 service类和dao类

(2)在service调用dao里面的方法

(3)在spring配置文件中进行配置

 <!--    创建UserDao对象和UserService对象-->
      <bean id="userService" class="com.lp.springDemo1.service.UserService">
  <!--    属性注入-->
          <property name="username" value="小明"></property>
          <property name="age" value="11"></property>
  <!--    外部bean注入-->
          <property name="userDao" ref="userDaoImpl"></property>
      </bean>
      <bean id="userDaoImpl" class="com.lp.springDemo1.dao.UserDaoImpl"></bean>
 public class UserService {
      private String username;
      private int age;
      private UserDao userDao;
  ​
      public void setUsername(String username) {
          this.username = username;
      }
  ​
      public void setAge(int age) {
          this.age = age;
      }
  ​
      public void setUserDao(UserDao userDao) {
          this.userDao = userDao;
      }
  ​
      public void look(){
          System.out.println("UserService.look()========");
          userDao.add();
      }
  ​
  }

3.注入属性——内部bean和级联赋值

(1)一对多关系:部门和员工

一个部门有多个员工,一个员工属于一个部门

(2)在实体类之间表示一对多关系,员工表示所属部门,使用对象类型进行表示

  //部门表
  public class Dept {
      private String dname;
  ​
      public void setDname(String dname) {
          this.dname = dname;
      }
  }
  //员工表
  public class Emp {
      private String ename;
      private String sex;
      //员工属于某个部门,使用对象形式表示
      private Dept dept;
  ​
      public void setEname(String ename) {
          this.ename = ename;
      }
  ​
      public void setSex(String sex) {
          this.sex = sex;
      }
  ​
      public void setDept(Dept dept) {
          this.dept = dept;
      }
  }
  <bean id="emp" class="com.lp.springDemo1.bean.Emp">
      <property name="ename" value="小王"></property>
      <property name="sex" value="男"></property>
      <property name="dept">
          <bean id="dept" class="com.lp.springDemo1.bean.Dept">
              <property name="dname" value="研发部"></property>
          </bean>
      </property>
  </bean>

4.注入属性——级联赋值

(1)第一种方法

<!--    级联赋值-->
      <bean id="emp" class="com.lp.springDemo1.bean.Emp">
          <property name="ename" value="小王"></property>
          <property name="sex" value="男"></property>
          <property name="dept" ref="dept"></property>
      </bean>
      <bean id="dept" class="com.lp.springDemo1.bean.Dept">
          <property name="dname" value="研发部"></property>
      </bean>

(2)第二种方法:生成get放法,

 //员工属于某个部门,使用对象形式表示(Emp表)
  private Dept dept;
  ​
  public Dept getDept() {
      return dept;
  }

xml配置文件

<bean id="emp" class="com.lp.springDemo1.bean.Emp">
      <property name="ename" value="小王"></property>
      <property name="sex" value="男"></property>
      <property name="dept.dname" value=""></property>
  </bean>
  <bean id="dept" class="com.lp.springDemo1.bean.Dept">
      <property name="dname" value="研发部"></property>
  </bean>

5.注入属性——xml注入集合属性

(1)注入数组类型属性

(2)注入List集合属性

(3)注入set集合属性

(4)注入Map集合属性

①创建类,定义数组、list、set、map类型属性,生成对应的set方法

 public class Stu {
      //1.数组类型属性
      private String[] courses;
      //2.list类型属性
      private List<String> list;
      //3.set类型属性
      private Set<String> sets;
      //4.map类型属性
      private Map<String,String> map;
  ​
      public void setCourses(String[] courses) {
          this.courses = courses;
      }
  ​
      public void setList(List<String> list) {
          this.list = list;
      }
  ​
      public void setSets(Set<String> sets) {
          this.sets = sets;
      }
  ​
      public void setMap(Map<String, String> map) {
          this.map = map;
      }
  }

②xml文件配置

  <!--注入集合类型属性-->
      <bean id="stu" class="com.lp.springDemo1.Demo1.Stu">
  <!--注入数组类型属性-->
          <property name="courses">
              <array>
                  <value>语文</value>
                  <value>数学</value>
              </array>
          </property>
  <!--注入list类型属性-->
          <property name="list">
             <list>
                 <value>Monday</value>
                 <value>Tuesday</value>
             </list>
          </property>
  <!--注入 set类型属性-->
          <property name="sets">
              <set>
                  <value>First</value>
                  <value>Second</value>
              </set>
          </property>
  <!--注入map属性类型-->
          <property name="map">
              <map>
                  <entry key="a" value="Java"></entry>
                  <entry key="b" value="PHP"></entry>
              </map>
          </property>
      </bean>

6.把注入集合部分提取出来

(1)在spring配置文件中引入名称空间util

 <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:util="http://www.springframework.org/schema/util"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                             http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

(2)使用util标签完成list集合注入提取

 <!--提取list集合类型属性注入-->
  <util:list id="bookList">
      <value>语文</value>
      <value>数学</value>
      <value>英语</value>
  </util:list>
  <!--提取list集合类型属性注入使用-->
  <bean id="storyBook" class="com.lp.springDemo1.book.StoryBook">
      <property name="bookname" ref="bookList"></property>
  </bean>

IOC操作Bean管理(FactoryBean)

1.Spring有两种类型bean,一种是普通bean,另一种是工厂bean(FactoryBean)

2.普通bean:在配置文件中定义bean类型就是返回类型

3.工厂bean:在配置文件定义bean类型可以和返回类型不一样

第一步:创建类,让这个类作为工厂bean,实现接口FactoryBean

第二步:实现接口里面的方法,在实现的方法中定义返回的bean类型

IOC操作Bean管理(bean作用域)

1、在Spring中,设置创建bean实例是单实例还是多实例

2、在Spring里面,默认情况下,bean是单实例对象

Spring中IOC容器

 

3、如何设置单实例还是多实例

(1)在Spring配置文件bean标签里面有属性(scope)用于设置爱单实例还是多实例

(2)scope属性值

第一个值(默认值):singleton ,表示的是单实例对象

第二个值: prototype ,表示的是多实例对象

 <bean id="userImp" class="com.spring2.UserImp" scope="prototype">
      <property name="list" value="userlist"></property>
  </bean>

(3)singleton和prototype的区别:

第一:singleton是单实例,prototype是多实例

第二:设置scope的值是singleton的时候,加载spring配置文件的时候就会创建单实例对象;

设置scope的值是prototype的时候,不是在加载Spring配置文件的时候就会创建对象,而是在调用getBean()方法的时候才会 创建多实例对象。

(4)scope另外的两个值:

request

session

IOC操作Bean管理(bean生名周期)

1、生命周期

(1)从对象的创建到对象的销毁的过程

2、bean生命周期

(1)通过构造器创建bean实例(无参数构造)

(2)为bean的属性设置值和对其他bean的引用(调用set方法)

(3)调用bean的初始化方法(需要进行配置)

(4)bean可以使用了(对象获取到了)

(5)当容器关闭的时候,调用bean的销毁的方法(需要进行配置的销毁的方法)

3、演示bean的声明周期的过程

IOC操作Bean管理(自动装配)

bean标签属性autowire,配置自动装配

autowire属性常用两个值:byName和byType

byName:根据属性名称注入

byType:根据属性类别注入

IOC操作Bean管理(基于注解)

1、Spring针对Bean管理中创建对象提供注解

①Component

②Service

③Contorller

④Repository

2、基于注解方式实现对象的创建

第一步:pom.xml 文件中 引入依赖

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.3.8</version>
  </dependency>

第二步:开启组件扫描

①引入空间名称:

 <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:p="http://www.springframework.org/schema/p"
         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">

②开启扫描组件

 <!--开启组件扫描
      1、如果扫描多个包,用逗号隔开
      2、也可以扫描他们共同的上层目录-->
      <context:component-scan base-package="com.lp"></context:component-scan>

第三步:创建类,在类上面添加创建对象注释

 //在注解中value属性值可以省略不写
  //默认是类名首字母小写
  @Component(value = "serviceTest")
  public class ServiceTest {
      public void  add(){
          System.out.println("service add()......");
      }
  }

注意细节:

①表示只扫描Controller注解,其他都不扫描

<context:component-scan base-package="com.lp" use-default-filters="false">
      <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  </context:component-scan>

②表示不扫描Controller注解,其他都扫描

 <context:component-scan base-package="com.lp">
      <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  </context:component-scan>

3、基于注解方式实现属性的注入

(1)@Autowired 根据属性类型进行自动装配

//定义dao类型属性

//不需要添加set方法

//添加注入属性的注解

  @Service
  public class UserService {
      @Autowired
      private UserDao userDao;
  ​
      public void  add(){
          System.out.println("service add()......");
          userDao.add();
      }
  }

(2)@Qualifier 根据属性名称进行注入

这个@Qualifier 注解的使用,和上面的@Autowired 一起使用。

//定义dao属性

//不需要添加set方法

  @Autowired
  @Qualifier(value = "userDao")
  private UserDao userDao;

(3)@Resource 即 可以根据类型注入,也可以根据名称注入

 @Resource(name = "userDao1")
  private UserDao userDao;

(4)@Value 注入普通类型属性

 @Value(value = "小明")
  private String name;

4、完全注解 开发(不要配置文件)

(1)创建配置类,代替xml文件

  @Configuration //作为配置类,代替xml文件
  @ComponentScan(basePackages = "com.lp")
  public class SpringConfig {
  }

(2)加载配置类

  //加载配置类
  ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);

上一篇:Spring 笔记 - 06 DI 依赖注入


下一篇:动态类型dynamic(ExpandoObject)