Web框架—Spring Framework学习笔记(IoC DI Bean)

Posted Putarmor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Web框架—Spring Framework学习笔记(IoC DI Bean)相关的知识,希望对你有一定的参考价值。

Spring是什么?

  • Spring是什么呢?我们可看一下官网的定义:
  • Spring快速、容易、安全,专注速度,开发效率高,Spring是全世界最流行的Java开发框架。
    在这里插入图片描述

Spring Framework框架

Spring Framework是Spring中的核心框架,结构如下所示:
在这里插入图片描述
Core Container(核心容器)模块主要是四部分构成:
Sping-Beans
Spring-Core
Spring-Context
Spring-Expression Language

1.IoC容器

IoC(Inversion of Control)称为控制反转,是面向对象编程中的一种设计原则,主要用来降低代码之间的高耦合度问题。

  • 从使用上看,使用IoC之前,创建对象需要手动new对象,并设置对象属性,控制权掌握在应用程序自身(对象的创建与销毁都掌握在我们自己手中);使用IoC之后,对象的控制权交给了第三方进行管理,这里的第三方就是容器,因而对象由容器来管理。因为发生了控制权的反转,所以叫控制反转。

2.DI(依赖注入)

DI(Dependency)称为依赖注入,是实现IoC的方法之一,所谓依赖注入就是指IoC容器运行期间,动态地将某种依赖关系注入到对象到中。

3.IoC与DI关系

实际上,IoC与DI是从不同角度描述的同一件事情,当引入IoC容器后,使用依赖关系注入的方式,实现了对象之间的解耦。


接下来主要针对Sping-Beans与Spring-Context进行介绍:

  • Spring容器的API有BeanFactoryApplicationContext两大类,二者都是顶级接口,其中ApplicationContext是BeanFactory的顶级接口。接下来的代码演示部分,我们都基于ApplicationContext应用上下文接口去实现容器。

我们先基于Maven创建Spring项目,具体步骤如下:

1.创建Maven项目后,在pom.xml配置文件中引入外部依赖,刷新Maven面板

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>SpringProject</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 注解 -->
    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-framework.version>5.2.10.RELEASE</spring-framework.version>
    </properties>

    <!-- 引入外部依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring-framework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring-framework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>
    </dependencies>

</project>

2.准备项目启动类入口

将beans.xml文件作为参数对ClassPathXmlApplicationContext类进行实例化操作,构建一个ApplicationContext对象。

package org.example;  //自定义启动类路径

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

    public static void main(String[] args) {
    
        ApplicationContext context = 
        new ClassPathXmlApplicationContext("beans.xml");
        //关闭容器
        ((ClassPathXmlApplicationContext)context).close();
    }
}

3.定义Spring配置文件(这里指的就是beans.xml)

在src/main/resources/下创建beans.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 包扫描路径 -->
    <context:component-scan base-package="org.example"/>  
    
</beans>

<context:component-scan base-package="org.example"/>
base-package:表示的是Spring启动时候扫描的包路径,该路径下带有类注解的类将被注册到容器里。

4.扫描Spring类注解注册Bean对象

类注解方式:共有4种类注解,它们虽然对应不同的业务,但是都是为Spring容器服务的;类注解定义方式默认会注册类名首字母小写的Bean对象到容器中。

  • @Controller :前端业务交互(参数校验)
  • @Service :业务处理中间类(业务逻辑处理)
  • @Repository :数据持久层(增删查改)
  • @Component :通用对象工具类(比如数据序列化、反序列化操作)
package org.example.controller;


import org.springframework.stereotype.Controller;

@Controller
public class LoginController1 {

}

5.得到容器中Bean对象

第一种得到Bean对象方式:
在这里插入图片描述在这里插入图片描述

需要特别注意的是:getBean方法中的参数首字母一定是小写的(源码表示启动类名首字母小写),否则代码引发异常

第二种得到Bean对象方式:
在这里插入图片描述在这里插入图片描述

从代码执行的结果可以看出:Bean对象被正常打印出来

两种方式拿到的对象是否一样呢?
在这里插入图片描述在这里插入图片描述
从结果可以看出两种方式获得的对象是同一个Bean对象,这是因为Spring使用了单例模式。


特殊情况:当注解类前两个字母都为大写时,传入的参数为原来的类名

package org.example.controller;

import org.springframework.stereotype.Controller;

@Controller
public class URLController {
}

在这里插入图片描述在这里插入图片描述

从代码执行结果来看,此时getBean方法传入的参数要求是原来的类名。


Lombok依赖

当在beans.xml中添加了Lombok依赖时,需要安装Lombok插件
在这里插入图片描述
Lombok使用演示:

package org.example.model;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Setter
@Getter
@ToString
public class User {
    private String name;
    private String password;
}

对上面代码build操作后,可以发现自动生成了三种方法
在这里插入图片描述

Lombok原理:它是自定义注解的方式,在代码编译时期,将自定义的注解更换成了JVM可以执行的方法(就是get、set、toString方法)。

注册Bean的方式

1.类注解

上面已经阐述,此处不再赘述。

2.@Bean注解

当前类被Spring扫描时,可以在方法上使用@Bean注解,通过方法返回类型,可以定义、注册Bean对象,默认使用方法名作为Bean的名称。

在LoginController中定义两个User方法:

 //返回User类型
    @Bean
    public User user1(){
        User user = new User();
        user.setName("小唐");
        user.setPassword("0627");
        return user;
    }

    @Bean
    public User user2(){
        User user = new User();
        user.setName("康康");
        user.setPassword("0215");
        return user;
    }

在这里插入图片描述
在这里插入图片描述
从结果可以看出@Bean方法注解成功注册了Bean对象。

那么能不能以同样的方式(或者Use.class方式)传入user2拿到Bean对象?
答案:不行,因为user1和user2方法返回的都是User类型,容器中注册的Bean对象有两个。

如何得到user2的Bean对象呢?
首先在LoginController类上加入Getter注解
在这里插入图片描述
在这里插入图片描述

3.@Configuration注解

当类被Spring扫描时,使用@Configuration注解,可以注册一个配置类到容器中,配置类一般用来自定义配置某些资源。

在这里插入图片描述
在这里插入图片描述从结果可以看出,使用Configuration注解注册了Bean对象。

依赖注入的方式

1.属性注入

package org.example.service;

import org.springframework.stereotype.Service;

@Service //存储Bean
public class LoginService {
    public void sayHi(){
        System.out.println("666666666666666666");
    }
}
package org.example.controller;

import org.example.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
@Getter
public class LoginController {

    //第一种方式:属性注入(查询Bean)
    @Autowired
    //这里变量名不能随意起,当同一个类有多个Bean对象时,会引发异常
    public LoginService loginService; 
    public void say(){
        loginService.sayHi();
    }

在这里插入图片描述在这里插入图片描述

结果说明在LoginController类中,通过属性注入的方式,可以得到Bean对象。

2.set方法注入

//第二种:set方式
    public LoginService loginService;  //这里的变量名可随意起
    @Autowired
    public void setLoginService(LoginService loginService) {
        this.loginService = loginService;
    }
    public void say(){
        loginService.sayHi();
    }

3.构造方法注入

//第三种:构造方法注入
    private LoginService loginService;
    
    @Autowired  //加不加都行
    public LoginController(LoginService loginService){
        this.loginService = loginService;
    }

    public void say(){
        loginService.sayHi();
    }

三种注入方式比较来看,属性注入的方式是最简洁的。

4.指定注入:@Qualifier

当同类型的Bean有多个时,注入该类型Bean需要指定Bean的名称:

  • 属性名或方法参数名设置为Bean的名称
  • 属性名或方法参数设置@Qualifier(“名称”)注解,注解内的字符串是Bean对象的名称。

Bean的作用域

Spring容器在初始化一个Bean对象时,同时会指定该对象的作用域,一共有6种作用域,接下来我们分别来看:

1.singleton
该作用域为单例模式作用域,Bean在IoC容器中只有一个实例对象,获取Bean(getBean)以及装配Bean(@Autowired)都是同一个对象。Spring容器默认默认选择的是singleton作用域

2.prototype
每次该作用域下Bean的请求都会创建新的实例,也就是说每一次的获取Bean和装配Bean都是新的对象。通常有状态的Bean使用该作用域

3.request
每次http请求都会创建新的Bean实例;适用场景:一次http请求和响应的共享Bean;限定在SpringMVC中使用。

4.session
在一个http的session中定义一个Bean实例;场景:http的session会话中记录一个用户的登录信息;限定在SpringMVC中使用。

5.application
在一个http servlet Context中,定义一个Bean实例;场景:Web应用的全局上下文信息,比如记录一个应用的共享信息;限定在SpringMVC中使用。了解即可

6.websocket
在一个http WebSocket的生命周期中,定义一个Bean实例;场景:WebSocket的每次会话中,保存了一个Map结构的头信息,用来包裹客户端的消息头,第一次初始化后,直到WebSocket结束都是一个Bean;限定在Spring WebSocket中使用。

Bean生命周期

  • 生命周期图
    在这里插入图片描述
  • Bean的生命周期主要步骤:

1.实例化Bean:通过反射机制调用构造方法实例化对象;
2.依赖注入:装配Bean的属性;
3.实现了Aware接口的Bean,执行接口的方法:顺序执行BeanNameAware、BeanFactoryAware、ApplicationContextAware的接口方法;
4.Bean对象初始化之前,循环调用实现了BeanPostProcessor接口的预初始化方法postProcessBeforeInitialization;
5.Bean对象初始化:顺序执行@PostConstruct注解方法、InitializingBean接口方法、init-method方法;
6.Bean对象初始化后,循环调用实现了BeanPostProcessor接口的后初始化方法
postProcessAfterInitialization;
7.容器关闭时调用Bean对象的销毁方法,顺序:@PreDestroy注解方法、@DisposableBean接口方法、destory-method。

以上是关于Web框架—Spring Framework学习笔记(IoC DI Bean)的主要内容,如果未能解决你的问题,请参考以下文章

web框架之Spring-MVC环境搭建(转)

学习使用Robot Framework自动化测试框架-web元素定位

学习使用Robot Framework自动化测试框架——Web元素定位

学习使用Robot Framework自动化测试框架——Web元素定位

Spring 5 新功能:函数式 Web 框架

如何搭建spring mvc框架