控制反转(IOC)

控制反转

1.1 IoC介绍

IoC (Inverse of Control)控制反转,将原本由我们手动完成的创建对象的工作交由Spring对象工厂来完成

1.2 Spring对象工厂使用
创建Bean
public class Book {
    private int bookId;
    private String bookName;
}
配置Bean
<?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标签将实体类 配置给 spring管理,id是当前实体类在Spring容器中的唯一标识 -->
    <bean id="book" class="com.qfedu.entity.Book"></bean>

</beans>
获取Bean
//a.加载spring配置文件
ClassPathXmlApplicationContext context = 
    new ClassPathXmlApplicationContext("applicationContext.xml");

//b.从Spring对象工厂获取对象
Book book = (Book)context.getBean("book");
1.3 DI(Dependency Injection) 依赖注入
★ set方法注入 :

使用property标签完成属性注入依赖于类中属性的set方法——set注入

1.3.1 依赖注入概念

Spring对象工厂完成对象创建的同时,为对象的属性赋值,称之为依赖注入。

  • 在配置文件指定bean的属性值
  • 通过对象工厂创建对象时,就会将指定的值注入
1.3.2 简单类型和字符串类型属性注入
public class Book {
    private int bookId;
    private String bookName;
}
<bean id="book" class="com.qfedu.entity.Book">
        <!--
        property标签,用于给创建的实例输入配置注入的值
        name 属性   指定对象的属性名
        value 属性  指定对象当前属性的值
        -->
        <property name="bookId" value="1001"/>
        <property name="bookName" value="Java程序设计"/>
</bean>
1.3.3 日期类型
public class Book {
    private int bookId;
    private String bookName;
    private Date bookTime;
}
  • 方式1:
<bean id="book" class="com.qfedu.entity.Book">
    <property name="bookId" value="1001"/>
    <property name="bookName" value="Java程序设计"/>
    <property name="bookTime" value="2020/07/29"/>
</bean>
  • 方式2:
<bean id="time" class="java.util.Date"/>

<bean id="book" class="com.qfedu.entity.Book">
    <property name="bookId" value="1001"/>
    <property name="bookName" value="Java程序设计"/>
    <property name="bookTime" ref="time"/>
</bean>
  • 方式3
<bean id="book" class="com.qfedu.entity.Book">
    <property name="bookId" value="1001"/>
    <property name="bookName" value="Java程序设计"/>
    <property name="bookTime" >
        <bean class="java.util.Date"/>
    </property>
</bean>
1.3.4 自建类型(自定义类类型)
public class Type {
    private int typeId;
    private String typeName;
}
public class Book {
    private int bookId;
    private String bookName;
    private Type type;
}
  • 方式1:
<bean id="book" class="com.qfedu.entity.Book">
    <property name="bookId" value="1"/>
    <property name="bookName" value="Java程序设计"/>
    <!--自定义类类型的属性-->
    <!--<property name="type" ref="type1"/>-->
    <property name="type">
        <bean class="com.qfedu.entity.Type">
            <property name="typeId" value="10003"/>
            <property name="typeName" value="地理"/>
        </bean>
    </property>
</bean>
  • 方式2:
<bean id="type1" class="com.qfedu.entity.Type">
    <property name="typeId" value="10001"/>
    <property name="typeName" value="IT"/>
</bean>

<bean id="book" class="com.qfedu.entity.Book">
    <property name="bookId" value="1"/>
    <property name="bookName" value="Java程序设计"/>
    <!--自定义类类型的属性-->
    <property name="type" ref="type1"/>
</bean>
1.3.5 集合类型
  • 单值集合(List\Set\数组)
public class Book {
    private List<String> marks;
    private Set<String> attrs1;
    private String[] attrs2;
}
<bean id="book" class="com.qfedu.entity.Book">
    <property name="marks">
        <list>
            <value>aa</value>
            <value>bb</value>
            <value>cc</value>
        </list>
    </property>
    <property name="attrs1">
        <set>
            <value>aa</value>
            <value>bb</value>
            <value>aa</value>
        </set>
    </property>
    <property name="attrs2">
        <array>
            <value>1</value>
            <value>2</value>
            <value>3</value>
            <value>4</value>
        </array>
    </property>
</bean>
  • 键值对集合(Map、Properties)
public class Book {
    private Map<String,Object> attrs3;
    private Properties attrs4;
}
<bean id="book" class="com.qfedu.entity.Book">

    <!--map-->
    <property name="attrs3">
        <map>
            <entry key="key1" value="value1"/>
            <entry key="key2" value-ref="date"/>
        </map>
    </property>
    <!--properties -->
    <property name="attrs4">
        <props>
            <prop key="k1">v1</prop>
            <prop key="k2">v3</prop>
        </props>
    </property>
</bean>
★ 构造器注入

如果类中没有set方法则不能使用property标签完成属性的注入,此时我们可以通过有参构造器完成注入

public class Type {

    private int typeId;
    private String typeName;

    public Type() {
    }

    public Type(int typeId, String typeName) {
        this.typeId = typeId;
        this.typeName = typeName;
    }
}
<bean id="type1" class="com.qfedu.entity.Type">
    <!--
        constructor-arg 指定构造器参数
        index属性指定构造器参数的索引
        value属性指定构造器参数的值
        ref属性,当构造器参数是对象类型时,用于指定对象
        -->
    <constructor-arg index="0" value="10001"/>
    <constructor-arg index="1" value="人文"/>
</bean>
1.4 使用SpringIoC解决项目中的耦合度问题
1.4.1 传统写法:Servlet对Service实现类存在依赖
public class LoginServlet extends HttpServlet {

    private UserService userService = new UserServiceImpl1();
    
    public void doGet(HttpServletRequest request,HttpServletResponse response){
        userService.login();
    }

}
1.4.2 解决方案
  • Servlet
public class LoginServlet extends HttpServlet {

    private UserService userService;
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    
    public void doGet(HttpServletRequest request,HttpServletResponse response){
        userService.login();
    }

}
  • 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="userService1" class="com.qfedu.service.impl.UserServiceImpl1"></bean>
    <bean id="userService2" class="com.qfedu.service.impl.UserServiceImpl2"></bean>

    <bean id="loginServlet" class="com.qfedu.servlets.LoginServlet">
        <property name="userService" ref="userService2"/>
    </bean>

</beans>
1.5 Bean的配置

bean标签,用来声明Spring容器对类的管理

  • id/name属性 是当前bean的唯一标识
  • class属性 用来指定被Spring容器管理的类路径
  • scope属性
  • lazy-init属性,设置Bean的初始化为懒初始化
  • autowire属性,设置Bean的属性自动装配
1.5.1 Bean的生命周期

通过scope属性可以指定对象的生命周期

  • singleton 默认 ,设置当前bean为单例模式(饿汉)

      1. Spring容器启动创建对象(分配内存空间):创建对象—调用构造器—调用set方法—初始化方法
      1. 对象创建完成存放在Spring容器
      1. Spring容器关闭销毁对象
  • prototype 设置当前Bean为非单例模式

      1. Spring容器启动不会创建对象(加载配置文件)
      1. 调用getBean使用对象时创建对象:创建对象—调用构造器—调用set方法—初始化方法
      1. 对象创建完成可使用
      1. 对象使用完成之后被JVM垃圾回收
  • scope配置
<bean id="type1" class="com.qfedu.entity.Type" scope="singleton">
    <property name="typeId" value="10001"/>
    <property name="typeName" value="人文"/>
</bean>
1.5.2 初始化和销毁方法

初始化方法:实例创建完成之后执行的方法

销毁方法:实例销毁时执行的方法

public class Type {

    private int typeId;
    private String typeName;

    public void method1(){
        System.out.println("-------init");
    }
    public void method2(){
        System.out.println("-------destory");
    }
}
<bean id="type1" class="com.qfedu.entity.Type" scope="singleton" lazy-init="true"  
      init-method="method1" destroy-method="method2">
    <property name="typeId" value="10001"/>
    <property name="typeName" value="人文"/>
</bean>
1.5.3 自动装配

Bean的属性(一般指的是对象属性)也可以通过自动装配来完成赋值,自动装配的两种方式:

  • byType 根据当前对象属性的类型 从Spring容器中选择类型匹配的bean进行注入;如果没有找到对应类型的bean,则设置为null;如果找到多个类型匹配的Bean则抛出异常
  • byName 根据当前对象属性的属性名 从Spring容器选择bean 进行注入;如果没有找到同名的bean则设置为null;如果根据属性名找到bean类型不匹配则抛出异常
<bean id="book" class="com.qfedu.entity.Book" autowire="byName"></bean>
1.6 Spring对象工厂的工作原理

Spring对象工厂原理:xml解析、反射

  • Spring工作原理概念图

在这里插入图片描述

二、IoC注解配置

SpringIoC的使用,通过将我们创建的类声明给Spring对象工厂进行管理来实现对象创建和属性注入的;

Spring也提供了注解的配置形式,无需再xml文件中进行声明,直接在类中通过注解的形式进行声明即可。

2.1 配置声明使用注解
  • 在spring配置文件applicationContext.xml添加context的命名空间
  • 通过context:annotation-config标签声明使用注解
  • 通过context:component-scan声明注解使用的范围
<?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">

    <context:annotation-config/>
    <context:component-scan base-package="com.qfedu.entity"/>

</beans>
2.2 IoC常用注解
@Component /@Service/@Repository
  • 类注解,声明类被Spring管理,相当于bean标签的作用
  • value值相当于 bean标签的id属性,如果不设置value值,则默认id为 类名首字母小写
  • @Service 用于声明Service; @Repository用于声明DAO ; @Component用于一般声明
@Autowired
  • 属性注解/方法注解,用于声明当前属性为自动装配,默认根据byType类完成自动注入

  • @Autowired(required = false) 声明此自动装配非必须的,默认是必须的

  • 当Spring容器由多个可以注入的Bean时,我们需要结合@Qualifier注解来指定注入的Bean

    @Autowired
    public void setType(@Qualifier("type1") Type type) {
        this.type = type;
    }
    
@Scope
  • 类注解,用于声明当前类对象是否为单例模式,默认单例
  • @Scope(“prototype”) 设置为非单例模式
@Lazy(false)
  • 类注解,用于设置当前类的Bean是否为懒汉式(针对单例模式)、
  • 默认值为true,@Lazy(false)设置为非懒汉式
@PostConstruct 和 @PreDestroy
  • 方法注解,用于声明声明周期方法
  • @PostConstruct 声明初始化方法
  • @PreDestroy 声明销毁方法
@PostConstruct
public void method1(){
    System.out.println("---init");
}

@PreDestroy
public void method2(){
    System.out.println("----destory");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值