Spring Framework

一.Spring Framework结构图

在这里插入图片描述

二.Core Container

1.模块:spring-core,spring-beans,spring-context,spring-expression(Spring Expression Language).
2. spring-context和spring-beans
简介

spring-context和spring-beans提供整个Spring框架的最基础设施:IoC(控制反转)和DI(依赖注入)

Ioc和DI
  • IoC(控制反转)
    是面向对象编程的一种设计原则,可以用来减低计算机代码之间的耦合度。
    系统中通过引入实现了IoC模式和IoC容器,即可由IoC容器来管理对象的生命周期,依赖关系等,从而使得应用程序的配置和依赖性规范与实际应用程序代码分离。
    使用上,以前手动new对象,并设置对象中属性的方式,控制权掌握在应用程序自身。现在全部转移到容器,由容器统一进行管理对象。因为控制权发生的扭转所以叫控制反转。
  • IoC容器:实现了IoC思想的容器就是IoC容器,比如Spring Framework。
  • DI(依赖注入):是实现IoC的方法之一。所谓依赖注入,就是由IoC容器在容器运行期间,动态地将某种依赖关系注入到对象之中。
    简而言之,依赖注入(DI)和控制反转(IoC)是从不同角度的描述的同一件事情,就是指引入IoC容器,利用依赖注入的方式,实现对象之间的解耦。

(1)耦合示例代码

class Car{
	private Framework framework;
	Car(int size){
		this.framework=new Framework(size);
	}
	public void run(){...}
}

class Framework{
	private Bottom bottom;
	Framework(int size){
		this.bottom=new Bottom(size);
	}
}

class Bottom{
	private Tire tire;
	Bottom(int size){
		this.tire=new Tire(size);
	}
}

class Tire{
	private int size;
	Tire(int size){
		this.size=size;
	}
}

class Test{
	public static void main(String []args){
	//依赖耦合:Car依赖于Framework,Framework依赖于Bottom,Bottom依赖于Tire
		int size=40;
		Car mycar=new Car(40);
		mycar.run();
	}
}

(2)解耦示例代码

class Car{
	private Framework framework;
	Car(Framework framework){
		this.framework=framework;
	}
	public void run(){...}
}
class Framework{
	private Bottom bottom;
	Framework(Bottom bottom){
		this.bottom=bottom;
	}
}

class Bottom{
	private Tire tire;
	Bottom(Tire tire){
		this.tire=tire;
	}
}

class Tire{
	private int size;
	Tire(int size){
		this.size=size;
	}
}

class Test{
	public static void main(String []args){
	//注入解耦:Tire注入Bottom,Bottom注入Framework,framework注入Car
		int size=20;
		Tire tire=new Tire(size);
		Bottom bottom=new Bottom(tire);
		Framework framework=new Framework(bottom);
		Car mycar=new Car(framework);
		mycar.run();	
	}
}
总结:IoC控制反转属于设计思想,DI依赖注入是实现IoC思想的实现技术。

三.Spring Framework容器使用流程

1.Spring容器图解

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

2.注册/初始化bean(存对象)
(1)方式1:类注解@Controller,@Service,@Component,@Repository
  1. 创建启动类
  2. 配置xml
  3. 创建注入类
  4. 获取bean对象
  • 创建启动类:ApplicationContext对象并传入扫描xml文件路径;只写文件名则默认在根路径resources目录下。
    在这里插入图片描述

  • 配置xml:设置组件扫描路径,base-package是告知哪些包中有类要托管需要扫描,达到节约时间,提高效率,而不是所有包都要扫描一遍
    在这里插入图片描述

  • 创建注入类:类加上注解(@Controller,@Service,@Component,@Repository)才表示将类托管(注入)给spring容器
    在这里插入图片描述

  • 获取bean对象:运行测试获取bean对象并关闭资源
    在这里插入图片描述
    在这里插入图片描述

扩展:获取bean对象方式

  1. getBean(“类的命名名称”):类的命名名称规则时一是类名首字母大写时需转换为小写;二是类名的首字母开始连续字母均大写时连续大写字母全部保持大写,三是其余情况均保持不变。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
public class App {
	public static void main(String[] args) {
		//参数文件路径为根路径直接在resources下
		ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
		LoginController loginController= (LoginController) context.getBean("loginController");
		System.out.println(loginController);
		//关闭资源
		((ClassPathXmlApplicationContext)context).close();
  1. getBean(类名.class)
public class App {
	public static void main(String[] args) {
		//参数文件路径为根路径直接在resources下
		ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
		LoginController loginController= (LoginController) context.getBean(LoginController.class);
		System.out.println(loginController);
		//关闭资源
		((ClassPathXmlApplicationContext)context).close();

(2)方式2:方法注解@Bean

当前类被Spring扫描到时,可在方法上使用@Bean注解,通过方法返回类型,也可以定义,注册Bean对象,默认使用方法名作为Bean的名称。
注意没有使用任何Spring的注解,类不会被扫描到。

  1. 创建启动类
  2. xml配置
  3. 创建类和方法,并使用@Bean
  4. 获取Bean对象
  • 创建启动类
    在这里插入图片描述

  • xml配置:配置扫描包
    在这里插入图片描述

  • 使用@Bean:将方法返回的对象托管至spring容器
    在这里插入图片描述
    在这里插入图片描述

  • 获取Bean对象:从spring容器获取Bean对象
    在这里插入图片描述

补充:多个相同类型的对象如User时不能使用类名.class获取因为无法区分
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3)方式3:类注解@Configuration

当类被Spring扫描到时,使用@Configuration.可以注册一个配置类到容器中。配置类一般用来自定义配置某些资源。之后会在SpringMVC中用到。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(4)方法4:FactoryBean接口(扩展了解)
  1. 类实现FactoryBean接口
  2. 实现getObject方法
  3. 获取对象
package org.springframework.beans.factory;

import org.springframework.lang.Nullable;

public interface FactoryBean<T> {
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class<?> getObjectType();

    default boolean isSingleton() {
        return true;
    }
}

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

@Getter
@Setter
@ToString
public class User {
    private String username;
    private String password;
}
import org.model.User;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Controller;

@Controller
public class Byfactorybean implements FactoryBean<User> {
    //返回Bean对象
    @Override
    public User getObject() throws Exception {
        User user=new User();
        user.setUsername("abc");
        user.setPassword("123");
        return user;
    }
    //返回类
    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
    //是否是单例对象
    @Override
    public boolean isSingleton() {
        return false;
    }
}
import org.model.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        //参数文件路径为根路径直接在resources下
        ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
        User user= (User) context.getBean("byfactorybean");
        System.out.println(user);
        //关闭资源
        ((ClassPathXmlApplicationContext)context).close();
 	}
 }
  • 类实现FactoryBean接口,实现getObject方法
    在这里插入图片描述

  • 获取对象
    在这里插入图片描述

3.依赖注入/依赖装配(取对象)

从Sping容器中取出某个对象,然后将该对象放到某个类中。

(1)方式1:属性注解@Autowired

@Autowired声明并初始化对象

import org.springframework.stereotype.Service;

@Service
public class LoginService {

    public void sayHi(){
        System.out.println("你好呀");
    }
}
//类加上注解(@Controller,@Service,@Component,@Repository)才表示将类托管给spring容器
@Controller
public class LoginController {
    //@Autowired属性注解:初始化对象
    @Autowired
    private LoginService loginService;
    public void say(){
        loginService.sayHi();
    }
}
public class App {
    public static void main(String[] args) {
        //参数文件路径为根路径直接在resources下
        ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
        LoginController loginController=context.getBean(LoginController.class);
        loginController.say();
        //关闭资源
        ((ClassPathXmlApplicationContext)context).close();
    }
}
  • 定义类托管至Spring
    在这里插入图片描述

  • 属性注解获取初始化的对象
    在这里插入图片描述

  • 测试
    在这里插入图片描述

(2)方式2:Set注入
@Controller
public class LoginController {
    //方式1:@Autowired属性注解:初始化对象
//    @Autowired
//    private LoginService loginService;

    //方式2:Set注入
    private LoginService loginService;
    @Autowired
    public void setLoginService(LoginService loginService) {
        this.loginService = loginService;
    }
    public void say(){
        loginService.sayHi();
    }
}
  • 定义类托管至Spring
    在这里插入图片描述

  • Set注入
    在这里插入图片描述

  • 测试
    在这里插入图片描述

(3)方式3:构造函数注入

不需要注解

@Controller
public class LoginController {
    //方式3:构造函数注入:不需要注解
    private LoginService loginService;
    public LoginController(LoginService loginService) {
        this.loginService = loginService;
    }

    public void say(){
        loginService.sayHi();
    }
}
  • 定义类托管至Spring
    在这里插入图片描述

  • 构造函数注入
    在这里插入图片描述

  • 测试
    在这里插入图片描述

(4)注入补充扩展:@Qualifier

适用于获取多个对象时无法区分时进行标识

  • 未标识@Qualifier

//类加上注解(@Controller,@Service,@Component,@Repository)才表示将类托管给spring容器
@Controller
public class LoginController {

    //方式1:@Autowired属性注解:初始化对象
    @Autowired
    private User user;
    public void say(){
        System.out.println(user);
    }
    //使用方法注解@Bean:表示将当前方法返回的对象托管至spring容器
    @Bean
    public User user1(){
        User user=new User();
        user.setUsername("张三");
        user.setPassword("123");
        return user;
    }
    @Bean
    public User user2(){
        User user=new User();
        user.setUsername("李四");
        user.setPassword("123");
        return user;
    }
}

public class App {
    public static void main(String[] args) {
        //参数文件路径为根路径直接在resources下
        ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
        LoginController loginController=context.getBean(LoginController.class);
        loginController.say();
        //关闭资源
        ((ClassPathXmlApplicationContext)context).close();
    }
}

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

  • 标识@Qualifier
//类加上注解(@Controller,@Service,@Component,@Repository)才表示将类托管给spring容器
@Controller
public class LoginController {
    @Autowired
    @Qualifier("user1")
    private User user;
    public void say(){
        System.out.println(user);
    }
    //使用方法注解@Bean:表示将当前方法返回的对象托管至spring容器
    @Bean
    public User user1(){
        User user=new User();
        user.setUsername("张三");
        user.setPassword("123");
        return user;
    }
    @Bean
    public User user2(){
        User user=new User();
        user.setUsername("李四");
        user.setPassword("123");
        return user;
    }
}

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

4.bean的作用域

Spring容器在初始化一个bean的实例时,同时会指定该实例的作用域。Spring有6个作用域,后四个在Spring MVC中使用。

(1)singleton
  • 描述:该作用域下Bean在IoC容器中只存在一个实例
  • 场景:无状态的Bean使用该作用域,无状态表示Bean对象的属性不需要更新。
  • 注意:Spring默认使用该作用域。
(2)prototype
  • 描述:每次对该作用域下的Bean的请求都会创建新的实例。
  • 场景:通常有状态的Bean使用该作用域。
(3)request
  • 描述:每次http请求都会创建新的Bean实例。
  • 场景:一次http的请求和响应共享Bean。
  • 注意:限定在Spring MVC中使用。
(4)session
  • 描述:在一个http session中,定义一个Bean实例。
  • 场景:用户会话共享Bean。
  • 注意:限定在Spring MVC中使用
(5)application
  • 描述:在一个http servlet context中定义一个Bean对象。
  • 场景:Web应用的上下文信息。
  • 注意:限定在Spring MVC中使用。
(6)websocket
  • 描述:在一个HTTP WebSocket的生命周期中,定义一个Bean实例。
  • 场景:WebSocket的每次会话中都会保存一个map结构的头信息,将用来包裹客户端信息头。第一次初始化后,直到WebSocket结束都是同一个Bean。
  • 注意:限定在Spring WebSocket中使用。
  • 测试使用

在类上加上@Scope(“作用域”)例如@Scope(“prototype”)

5. Bean的生命周期

在这里插入图片描述

  1. 实例化Bean:通过反射调用构造方法实例化对象
  2. 依赖注入:装配Bean的属性
  3. Bean对象初始化:调用一系列接口
  4. 销毁Bean对象,容器关闭。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值