【spring】4. spring的核心思想之控制反转IOC(Inversion Object Control)

12 篇文章 0 订阅

1 IOC的基本概念

spring通过IOC容器来管理所有Java对象的实例化和初始化 -> Spring Bean

1.1 IOC容器

  • 容器使用Map来保存bean对象
  • xml配置文件:保存Bean的定义信息BeanDefinition

1.2 依赖注入DI(Dependency Injection)

控制反转之后,获得依赖对象的过程由对象自身控制变为了被动接受IOC容器中配置的属性注入的依赖
有两种依赖注入的方法

  • set注入

  • 构造注入

1.3 IOC容器在Spring的实现

在创建bean之前,需要先创建IOC容器
有两种创建方法

  • BeanFactory
    是Spring内部使用接口,不对外
  • ApplicationContext
    BeanFactory的子接口 √

    具体创建IOC的方法
类型名简介
ClassPathXmlApplicationContext通过读取类路径下的 XML 格式的配置文件创建 IOC 容器对象
FileSystemXmlApplicationContext通过文件系统路径读取 XML 格式的配置文件创建 IOC 容器对象
ConfigurableApplicationContextApplicationContext 的子接口,包含一些扩展方法 refresh() 和 close() ,让 ApplicationContext 具有启动、关闭和刷新上下文的能力。
WebApplicationContext专门为 Web 应用准备,基于 Web 环境创建 IOC 容器对象,并将对象引入存入 ServletContext 域中。

2 基于xml管理bean

2.1 获取bean的方法

首先在xml中进行配置


  • 通过id获取
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml")
Object object = context.getBean("user");
User user1 = (User)Object;
  • 通过类型获取 这种方式只能有一个
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml")
User user2 = context.getBean(User.class);
  • 通过id和类型获取
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml")
User user3 = context.getBean("user", User.class);

2.2 依赖注入

类有属性,创建对象过程中,向属性设置值

  • setter注入
    在xml配置文件中设置property属性等同于调用setter(),因此需要在类中先生成相应的setter()方法
<?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">
<!--    set方法注入-->
<bean id="book1" class="com.atguigu.spring6.iocxml.di.Book">
    <property name="bname" value="spring"></property>
    <!-- 外部bean注入 -->
    <property name="author" ref="user"></property>
    <!-- 内部bean注入 -->
    <property name="category">
     	<bean id="category2" class="com.atguigu.spring6.iocxml.di.category">
     	</bean>
    </property>
</bean>
<bean id="user" class="com.atguigu.spring6.iocxml.di.User">
</bean>
</beans>

注意,如果是“value”则为字面量,即字符串;
如果是"ref"则为对应的类,可以注入类对象

  • 构造器注入
    使用有参构造方法 在xml配置文件中设置constructor属性等同于调用有参构造方法,因此需要在类中先生成相应的constructor()方法
<?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="book2" class="com.atguigu.spring6.iocxml.di.Book">
        <constructor-arg name="bname" value="spring"></constructor-arg>
        <constructor-arg name="author" value="author2"></constructor-arg>
    </bean>
</beans>

一些特殊值处理

  • null
<property name="info">
	<null/>
</property>
  • xml的一些特殊字符 如“<”,“>”
<!-- 小于号大于号在XML文档中用来定义标签的开始,不能随便使用 -->
<!-- 解决方案一:使用XML实体来代替 -->
<property name="expression1" value="a &lt; b"/>
<property name="expression2" value="a &gt; b"/>
  • CDATA:
    被<![CDATA[]]>包含的内容是纯文本,比如<![CDATA[<]]>表示文本内容“<”,在xml文档中,”<”、”>”、”&”等字符是不能直接存入的。如果想在xml中使用这些符号,必须先转义为实体,才能保存进xml文档。在使用程序读取的时候,解析器会自动将这些实体转换回”<”、”>”、”&”。
<property name="expression">
    <!-- 解决方案二:使用CDATA节 -->
    <!-- CDATA中的C代表Character,是文本、字符的含义,CDATA就表示纯文本数据 -->
    <!-- XML解析器看到CDATA节就知道这里是纯文本,就不会当作XML标签或属性来解析 -->
    <!-- 所以CDATA节中写什么符号都随意 -->
    <value><![CDATA[a < b]]></value>
</property>

2.3 引入外部属性文件

以使用druid连接数据库为例,将数据库的连接属性写在外部属性配置文件中
这么写的好处是:如果数据库连接发生改变,不需要更改代码内容,只需要维护属性文件即可

  1. 加入依赖
 <!-- MySQL驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
</dependency>

<!-- 数据源 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.15</version>
</dependency>
  1. 创建外部属性文件
    定义数据库的属性:用户名,密码,地址
jdbc.user=root
jdbc.password=密码
jdbc.url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC
jdbc.driver=com.mysql.cj.jdbc.Driver
  1. 更改数据库配置文件的头部
<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/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
  1. 在配置文件中
    • 引入数据库属性文件
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
  • 完成数据库信息注入
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="url" value="${jdbc.url}"/>
    <property name="driverClassName" value="${jdbc.driver}"/>
    <property name="username" value="${jdbc.user}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>
  1. 在正式代码中进行数据库连接
    test1()中为外部注入方法,test2()为原写法
public class TestJdbbc {
    @Test
    public void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-jdbc.xml");
        DruidDataSource druidDataSource = (DruidDataSource) context.getBean("druidDataSource");
        System.out.println(druidDataSource.getUrl());
    }
    @Test
    public void test2(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl("jdbc:mysql://localhost:3306/spring?serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        System.out.println(dataSource);
    }
}

2.4 bean的作用域

scope属性

  • singleton:单实例,默认的属性,只能生成一个(对应的地址是一样的),在容器创建时即生成
  • prototype:多实例,在获取具体bean时即生成

2.5 bean的生命周期

  1. bean对象创建,调用无参数构造
  2. bean对象属性注入(普通属性和类属性)
  3. bean后置处理器(初始化之前)
  4. bean对象初始化(调用指定初始化方法)
  5. bean后置处理器(初始化之后)
  6. bean对象创建完成
  7. bean对象销毁
  8. IOC容器关闭

2.6 自动装配

  • autowire=“byName”
  • autowire=“byType”

3 基于注解管理bean

3.1 开启组件扫描

spring默认不使用注解装配Bean,因此需要在xml文件中开启组件扫描功能

  1. 更改xml的头部
  2. 增加组件扫描,其中com.atguigu.spring6说明在com.atguigu.spring6及其子包内使用注解
<?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-3.0.xsd
    http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    <!--开启组件扫描功能-->
    <context:component-scan base-package="com.atguigu.spring6"></context:component-scan>
</beans>

3.2 注解类型

注解说明
@Component该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。
@Repository该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Service该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Controller该注解通常作用在控制层(如SpringMVC 的 Controller层),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。

3.3 注入方式-@autowired注入

注意:都需要打开组件的自动扫描

    1. 属性注入,会自动根据类型进行匹配
      • 定义类的属性,将@Controller,@Service等注解在相应的类上(不在接口上)
      • 在@autowired标注在属性上
        在这里插入图片描述
        本图为UserControllerl类中定义userService-构造方法-直接定义
    1. set注入
    • 定义一个属性与其setter方法
    • 在属性的setter方法上标注@autowired
      本图为UserControllerl类中定义userService
      本图为UserControllerl类中定义userService-setter方法
    1. 构造方法进行注入
    • 定义一个属性与带有该属性的构造方法
    • 在该构造方法上进行标注@autowired
      在这里插入图片描述
      本图为UserControllerl类中定义userService-构造方法
      1. 形参方法进行注入
  • 定义一个属性与带有该属性的构造方法

  • 在该构造方法内部的形参上进行标注@autowired
    在这里插入图片描述

3.4 注入方式-@resource注入

@Resource注解和@Autowired注解的区别

  • @Resource注解是JDK扩展包中的,也就是说属于JDK的一部分。所以该注解是标准注解,更加具有通用性。(JSR-250标准中制定的注解类型。JSR是Java规范提案。)
  • @Autowired注解是Spring框架自己的。
  • @Resource注解默认根据名称装配byName,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型byType装配。
  • @Autowired注解默认根据类型装配byType,如果想根据名称装配,需要配合@Qualifier注解一起用。
  • @Resource注解用在属性上、setter方法上。
  • @Autowired注解用在属性上、setter方法上、构造方法上、构造方法参数上。
    注意:都需要打开组件的自动扫描
    步骤如下:
  • 增加依赖(高于JDK11或低于JDK8需要引入依赖)
<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>
  • 使用
package com.atguigu.spring6.service.impl;

import com.atguigu.spring6.dao.UserDao;
import com.atguigu.spring6.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Resource(name = "myUserDao") //根据name注入
    @Resource //name未知注入
    private UserDao myUserDao;

    @Override
    public void out() {
        myUserDao.print();
        System.out.println("Service层执行结束");
    }
}

3.5 全注解开发

全注解开发就是不再使用spring配置文件,写一个配置类来代替配置文件。

package com.atguigu.spring6.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
//@ComponentScan({"com.atguigu.spring6.controller", "com.atguigu.spring6.service","com.atguigu.spring6.dao"})
@ComponentScan("com.atguigu.spring6")
public class Spring6Config {
}

测试类

@Test
public void testAllAnnotation(){
    ApplicationContext context = new AnnotationConfigApplicationContext(Spring6Config.class);
    UserController userController = context.getBean("userController", UserController.class);
    userController.out();
    logger.info("执行成功");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值