spring

时间:2024-10-18 13:08:49

IoC、DI和AOP思想

IoC控制反转思想,强调是程序中将创建bean(主动new 创建对象)的权利反转给第三方

DI依赖注入思想,强调的是bean之间的依赖关系

AOP面向切面思想,功能的横向抽取,主要的实现方式就是proxy

IoC解决了哪些问题

 上图代码中,业务层内通过new BookDaoImpl实例化bookDao,由bookDao进行具体的数据操作,当需要将BookDaoImpl换成BookDaoImpl2时,就需要修改业务层的代码,代码的耦合性高,为了解决这个问题,引出了IoC思想,即:程序中将创建bean(主动new 创建对象)的权利反转给第三方(容器)

spring实现了这个第三方(容器),也被称为IoC容器,这个容器内部帮我们创建了对象,IoC容器创建的对象也被称为bean

IoC容器内将serice与dao建立关系就是DI 

IoC使用 

  • 管理什么?(Service与Dao)
  • 如何将被管理的对象告知IoC容器?(配置)
  • 被管理的对象交给IoC容器,如何获取到IoC容器?(接口
  • IoC容器得到后,如何从容器中获取bean?(接口方法)
     

首先是不使用IoC的代码案例: 

package org.example;

import org.example.dao.BookDao;
import org.example.service.BookService;
import org.example.service.impl.BookServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        BookService bookService = new BookServiceImpl();
        bookService.save();

    }
}

输出:
book service save ...
book dao save

 IoC入门 - 基于XML的IoC

1.pom.xml中配置依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>6.1.12</version>
</dependency>

2.xml中配置bean

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">

<!--    id是bean的名字, class是实现类-->
    <bean id="bookDao" class="org.example.dao.impl.BookDaoImpl" />
    <bean id="bookService" class="org.example.service.impl.BookServiceImpl" />
</beans>

 id是bean的名字, class是bean的实现类

3.使用bean

package org.example;

import org.example.dao.BookDao;
import org.example.service.BookService;
import org.example.service.impl.BookServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        // 获取IcC容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取bean
//        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
//        bookDao.save();
        BookService bookService = (BookService) ctx.getBean("bookService");
        bookService.save();
    }
}

DI使用

  • 前提是基于IoC管理的bean
  • Service中使用new形式创建的Dao对象是否保留?(否)
  • Service中需要的Dao对象如何引入到Service中?(提供方法)
  • Service与Dao间的关系如何描述?(配置)

 DI入门 - 基于XML的DI 

setter方法注入

引用类型注入 
xml中 使用property标签 + name + ref
package org.example.service.impl;

import org.example.dao.BookDao;
import org.example.service.BookService;

public class BookServiceImpl implements BookService {
    // 1.删除Service中使用new创建的Dao对象
//    private BookDao bookDao = new BookDaoImpl() ;
    private BookDao bookDao;

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
    // 2.Service中提供set方法创建Dao, 这个set方法是IoC容器调用的,通过xml中配置内容将bookDao传入
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}
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">

<!--    id是bean的名字, class是实现类-->
    <bean id="bookDao" class="org.example.dao.impl.BookDaoImpl" />
    <bean id="bookService" class="org.example.service.impl.BookServiceImpl">
<!--        3.配置Service与Dao的关系-->
<!--        name 表示配置哪一个具体属性-->
<!--        ref 表示参照哪一个bean-->
        <property name="bookDao" ref="bookDao"/>
    </bean>
</beans>

值类型注入

xml中 使用property标签 + name + value

package org.example.service.impl;

import org.example.dao.BookDao;
import org.example.service.BookService;

public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    private int year;
    private String name;

    public void save() {
        System.out.println("book service save"+name+year);
        bookDao.save();
    }
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public void setName(String name) {
        this.name = name;
    }
}
<?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="bookDao" class="org.example.dao.impl.BookDaoImpl" />
    <bean id="bookService" class="org.example.service.impl.BookServiceImpl" scope="prototype">
<!--        引用类型注入-->
        <property name="bookDao" ref="bookDao"/>
<!--        值类型注入-->
        <property name="year" value="2024"/>
        <property name="name" value="《java入门》"/>
    </bean>
</beans>

构造器注入

引用类型注入
xml中 使用constructor-arg标签 + name + ref  name可以换成type或index
package org.example.service.impl;

import org.example.dao.BookDao;
import org.example.service.BookService;

public class BookServiceImpl implements BookService {
    private BookDao bookDao;

    public BookServiceImpl(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}
<?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="bookDao" class="org.example.dao.impl.BookDaoImpl" />
    <bean id="bookService" class="org.example.service.impl.BookServiceImpl" scope="prototype">
        <constructor-arg name="bookDao" ref="bookDao"/>
    </bean>
</beans>
值类型注入 
xml中 使用constructor-arg标签 + name + value  name可以换成type或index
package org.example.service.impl;

import org.example.dao.BookDao;
import org.example.service.BookService;

public class BookServiceImpl implements BookService {
    private int year;
    private String name;

    public BookServiceImpl(int year, String name) {
        this.bookDao = bookDao;
        this.year = year;
        this.name = name;
    }
}
<?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="bookDao" class="org.example.dao.impl.BookDaoImpl" />
    <bean id="bookService" class="org.example.service.impl.BookServiceImpl" scope="prototype">
        <constructor-arg name="bookDao" ref="bookDao"/>
        <constructor-arg name="year" value="2024"/>
        <constructor-arg name="name" value="《java入门》"/>
    </bean>
</beans>

自动注入

配置中使用bean标签autowire属性设置自动装配的类型

  • 自动装配用于引用类型依赖注入,不能对简单类型进行操作
  • 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
  • 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
  • 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
     
案例
// 当使用自动注入时,会先找到set方法,然后:
// 1. autowire="byType" 时 会在bean中找到符合BookDao类型的bean来注入
// 2. autowire="byName" 时 会在bean中找到符合名字为 bookDao 的bean来注入

补充:依赖注入bean标签常用属性

 

spring 集合注入格式-****博客

Bean

bean基础

在Spring框架中,"bean" 是指由Spring IoC(Inversion of Control,控制反转)容器管理的任何对象。Spring IoC容器负责实例化、配置和组装这些bean。简单来说,bean就是应用程序中的一个组件或服务,它是由Spring IoC容器创建并管理的。

以下是关于Spring bean的一些关键点:

  • 定义:通常,你通过在Spring配置文件中使用<bean>标签或者使用注解(如@Component, @Service, @Repository, @Controller等)来定义一个bean。
  • 生命周期管理:Spring容器不仅创建bean,还管理它们的整个生命周期,包括初始化和销毁阶段。你可以通过实现特定的接口(如InitializingBean和DisposableBean)或使用自定义的初始化和销毁方法来控制这个过程。
  • 依赖注入:Spring的一个核心特性是依赖注入(DI, Dependency Injection),它允许你在不直接构造的情况下将一个bean的依赖关系提供给另一个bean。这意味着你不需要在代码中硬编码依赖项,而是可以通过配置让Spring容器自动完成依赖关系的装配。
  • 作用域:每个bean都可以指定一个作用域,比如singleton(单例,每个Spring IoC容器只有一个共享的bean实例)、prototype(原型,每次请求都会产生一个新的bean实例)、request、session等。
  • 配置方式:bean可以通过XML配置文件、Java配置类或注解来定义。随着Spring的发展,基于注解的配置变得越来越流行,因为它更加简洁且易于维护。
  • AOP支持:Spring beans还可以利用Spring AOP(面向切面编程)功能,在运行时动态地添加额外的行为,比如日志记录、事务管理等。

案例

<bean id="bookDao" class="org.example.dao.impl.BookDaoImpl" />
<bean id="bookService" class="org.example.service.impl.BookServiceImpl">

bean的别名

获取bean时,可以通过id获取也可以通过别名获取

 案例

<bean id="bookDao" name="dao,dao1" class="org.example.dao.impl.BookDaoImpl" />
<bean id="bookService" class="org.example.service.impl.BookServiceImpl"/>

 bean的作用范围

默认获取的bean是单例模式的

案例

<bean id="bookService" class="org.example.service.impl.BookServiceImpl" scope="prototype">
package org.example;

import org.example.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        // 获取IcC容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取bean
        BookService bookService1 = (BookService) ctx.getBean("bookService");
        BookService bookService2 = (BookService) ctx.getBean("bookService");
        System.out.println(bookService1);
        System.out.println(bookService2);
    }
}
输出:scope="prototype" 时获取的bean地址不同
org.example.service.impl.BookServiceImpl@6279cee3
org.example.service.impl.BookServiceImpl@4206a205

由于IoC容器管理的bean是默认是单例模式,哪些类适合交给IoC容器?

适合:

  • 表现层对象
  • 业务层对象
  • 数据层对象
  • 工具对象

不适合 

  • 封装实体的域或对象

bean的实例化

无参构造方法实例化bean

bean本质是对象,创建bean使用构造方法完成,且使用的是无参构造方法

静态工厂方法实例化bean

 工厂对象方法实例化bean

 FactoryBean实例化bean

 bean的生命周期

执行生命周期方法一

xml中配置init-mothod 与 destory-mothod

执行生命周期方法二

继承 InitializingBean 与 DisposableBean

手工关闭容器
ConfigurableApplicationcontext接口close()操作

注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机

ConfigurableApplicationcontext接口registerShutdownHook()操作

补充:

获取bean的方式

 bean标签常用属性

 

Spring framework