likes
comments
collection
share

Spring

作者站长头像
站长
· 阅读数 15

Spring 基础与核心概念

spring 是包含了众多工具方法的 IoC 容器。

什么是 IoC ?

IoC = Inversion of Control 翻译成中⽂是“控制反转”的意思,也就是说 Spring 是⼀个“控制反转”的容

器。控制反转,更确切的理解是控制权的反转。要理解控制反转,我们从以下实例出发:

以开发一辆汽车为例:

传统开发:

Spring

控制反转后:

Spring

传统代码是 Car 控制并创建了Framework,Framework 创建并创建了 Bottom,依次往下,⽽改进之后的控制权发⽣的反转,不再是上级对象创建并控制下级对象了,⽽是下级对象把注⼊将当前对象中,下级的控制权不再由上级类控制了,这样即使下级类发⽣任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是 IoC 的实现思想。

Spring 的核心功能:如何将对象存入到Spring当中,如何从Spring当中获取对象。

DI 介绍: dependency injection 依赖注入

所谓依赖注⼊,就是由 IoC 容器在运⾏期间,动态地将某种依赖关系注⼊到对象之中。

简单小结:Spring 是一个框架,IoC 是一种思想,DI 是 IoC 的具体实现。

创建Spring项目:

创建一个普通的maven项目:

Spring

Spring

添加Spring依赖:

1.对当前项目和新项目配置国内源:

Spring

Spring

2.更改setting.xml 中的镜像

Spring

3.删除原repository中的文件,重新加载:

Spring

Spring

4.引入依赖:

Spring

添加启动类:

Spring

将Bean对象存储到Spring容器中并获取和使用

  1. 创建一个Bean,在Java当中,如果一个类被多次调用,那么就可以称之为Bean.

Spring

2.将Bean存储到spring容器中

Spring

3.从Bean中获取对象

Spring

Spring

获取 Bean 的三种方式:

  1. 通过名称获取:不推荐

Spring

  1. 通过类名获取:不推荐

Spring

当一个类在 spring 中存储多份时,使用该方法出错:

Spring

  1. 推荐的方式:通过名称+类名的方式:

Spring

更为简单的存储和获取 Bean 对象的方式:注解

常用的几大类注解:

Spring

Spring

前置工作:配置扫描路径

Spring

Spring

得到Bean对象:其中得S有两种命名规则,若原类名得第一个字母和第二个字母均为大写,则S为原类名,若不是,则将原类名得第一个字母变为小写后使用:

Spring

Spring

不同包下出现同名类时:在对类进行存储时起别名,否则会报错,尽量避免两个类名相同。

Spring

五大类注解有什么关系?

Spring

为什么需要五大类注解:

为了方便程序员更好得区分当前类得作用。

JavaEE标准分层:

Spring

阿里标准分层:

Spring

实体类的命名规则:

Spring

使用方法注解@Bean 存储对象到spring容器中:

Bean是将方法得返回值存入spring,因此使用Bean注解得方法必须有返回值。

Spring

Bean 重命名:

Spring

同一个类型的对象存储多份时,后者会将前者覆盖,通过@Order注解来控制存入的顺序,值为1-100,数字越小先存入,后者将前者覆盖。

Spring

Spring

输出结果为:张三。

获取Bean对象

在当前基于Spring_core 框架的项目中,无法在启动类的main方法中获取到Bean对象,因为当前static修饰的类加载优先于Bean。

1.属性注入

Spring

单一设计原则:一个类只实现一个功能,当一个类中通过属性注入多个对象时,就会违背单一设计原则。

2.setter注入

Spring

3.构造方法的注入

Spring

@Resource 和 @Autowired 的区别:

1.两者来源不同,前者来自 JDK,后者来自 Spring.

2.两者都可以用于对象注入,但是前者不能用于构造方法的注入

3.前者拥有更多的属性内容,后者只有是否必须加载一个属性:

Spring

4.在Spring容器中,查找Bean的方式有两种,一种是按照类型查找,一种是按照名称查找,@Autowired 注解先根据类型查找,再根据名称查找,而@Resource注解刚好相反。

Lombok 的使用

  1. 引入依赖:

Spring

  1. 在实体类上使用其提供的注解

Spring

  1. 装Lombok插件:

Spring

Bean 的作用域和生命周期

先来看一个例子:

创建实体类:

Spring

原始数据:

Spring

在controller中分别注入当前的数据,并在第一个中进行数据修改:

Spring

Spring

在启动程序中调用两个controller:

Spring

此时,我们发现,当一个Bean被修改后,别处获取到的Bean数据也发生了改变。

Bean 作用域默认是单例模式 = 该 Bean 在整个spring容器中只存在一份。

Spring

Spring

spring 的执行流程:

Spring

Bean 的生命周期:从诞生到销毁

  1. 开辟内存空间,进行Bean的实例化;

  2. 设置属性(属性注入):在初始化时可能会使用到属性,因此要先进行属性注入;

  3. 初始化

    3.1 各种通知

    3.2 初始化前置方法

    3.3 初始化方法(两种实现方式,一种是xml,一种是通过注解)

    3.4 初始化后置方法

  4. 使用Bean

  5. 销毁Bean

代码示例:

public class ComponentBeans implements BeanNameAware, BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化前置方法");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化后置方法");
        return  bean;
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("通知 setBeanName "+ s);
    }

    public void myInit(){
        System.out.println("XML 方式的初始化方法");
    }

    @PostConstruct
    public void doPostConstruct(){
        System.out.println("注解方式的初始化方法");
    }

    public void saiHi(){
        System.out.println("使用Bean");
    }

    @PreDestroy
    public void doPreDestroy(){
        System.out.println("执行了销毁方法");
    }
}
public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        ComponentBeans componentBeans = context.getBean("componentBeans",ComponentBeans.class);
        componentBeans.saiHi();
        context.close();
    }
}

输出结果:

Spring

说明:

  1. 为何通知执行了两次,一次是在new 对象时进行初始化,一次是在getBean 时初始化;

  2. 为何没有执行销毁方法,因为多例模式下,销毁bean是直接停止线程,故不会执行销毁时的方法。

  3. 前置方法和后置方法只有作用域为原型模式时才执行。