Spring 概述

(我是先学了springboot,现在穿越回来啃啃spring老祖宗,看看有什么不一样的发现)

Spring 是最受欢迎的企业级 Java 应用程序开发框架,数以百万的来自世界各地的开发人员使用 Spring 框架来创建性能好、易于测试、可重用的代码。(以上是官方话)

简单来说:spring诞生的目的是为了解决企业应用开发的复杂性!

创始人:Rod Johnson ----一个音乐学博士 有点东西给是?

两个开发框架组合:

SSH:Struct2 + Spring + Hibernate

SSM: SpringMvc + Spring + Mybatis

Spring的优点:

1.Spring是一个开源的、免费的框架。

2.Spring是一个轻量级的、非入侵式的框架(非入侵就是在原有项目中导入spring项目,不会影响原项目。)

3.控制反转、面向切面编程(AOP)

4.支持事物处理,对框架整合的的支持。

IoC本质.

IoC在SpringBoot笔记中已经说明了,这里不做过多的解释了。

控制反转loC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法。

没有IoC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序

中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方。

创建第一个Spring

需要先给出官方文档地址:

https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html

先生成一个实体类

package com.heyexi.pojo;public class Hello
{private String name;public String getName(){return name;}public void setName(String name){this.name = name;}@Overridepublic String toString(){return "Hello{" +"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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"></beans>

然后就可以在里面配置我们的Javabean了。

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="hi" class="com.heyexi.pojo.Hello"><property name="name" value="何夜息"></property></bean>
</beans>

我们要自动装配一个bean,那么可以通过bean标签来设置,配置一个bean就相当于实例化了一个对象,把这个对象交给spring去管理,需要用到时候我们只需要通过spring上下文就可以获取了。

其中:id是相对于对象的名字,例如: Dog hsq = new Dog();那么id就是hsq,然后后面的class是告诉spring这个实体类的具体位置。

那么如何给这个对象设置属性呢?

可以通过下面的property 标签来设置对象的属性,name就是属性名,value就是值,也很简单,很好理解。

既然我们已经配置好了,那么如果获取呢?通过:实例化容器(ApplicationContext )来获取:!

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Mytest
{public static void main(String[] args){//获取Spring上下文对象,这句话是固定写法//ClassPathXmlApplicationContext里面可以写多个xml配置文件的名字ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");System.out.println(applicationContext.getBean("hi"));}
}

可以看到,我们在测试类中先生成一个ApplicationContext 对象,这个是用来获取bean对象的。

然后通过getBean("bean的ID")就可以获取到我们配置的对象了,如输出结果如下:可以看到成功获取了对象,而不必须我们去自己new一个对象,这就会控制反转。

7月 10, 2020 4:27:03 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
Hello{name='何夜息'}

注意,如果我们自定义了有参构造方法,那么配置文件中的bean就会报错,因为IOC创建不了无参对象,所有才会有Javabean的规范,就是要有无参构造方法。

那要如何配置有构造参数的bean呢?有多种方法,这里使用获取构造方法下标,也就是使用第几个构造方法来配置。

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="hi" class="com.heyexi.pojo.Hello"><constructor-arg index="0" value="何夜息"></constructor-arg></bean>
</beans>

可以看到是使用了<constructor-arg>这个标签来说创建的。

还有一种最常用的方式,就是通过直接构造方法中的参数赋值就行。

<bean id="hi" class="com.heyexi.pojo.Hello"><constructor-arg name="name" value="何夜息"></constructor-arg>
</bean>

name的值跟的就是构造方法的参数名!!例如假设构造参数多了一个age,那么我们可以:就很方便!!!

<bean id="hi" class="com.heyexi.pojo.Hello"><constructor-arg name="name" value="何夜息"></constructor-arg><constructor-arg name="age" value="20"></constructor-arg>
</bean>

特别重要的一个知识点:不管bean是否被调用,只要在配置文件中配置了,那么IOC就已经把对象给创建好了!

比如:我新建了一个实体类--User,然后在无参构造方法中输出一段话,也就是只要这个类被实例化就输出这句话!

package com.heyexi.pojo;public class User
{private String name;private Integer id;public User(){System.out.println("用户被创建!");}public String getName(){return name;}public void setName(String name){this.name = name;}public Integer getId(){return id;}public void setId(Integer id){this.id = id;}
}

然后我把它装配到配置文件中:

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--    <bean id="hi" class="com.heyexi.pojo.Hello">-->
<!--        <constructor-arg index="0" value="何夜息"></constructor-arg>-->
<!--    </bean>--><bean id="hi" class="com.heyexi.pojo.Hello"><constructor-arg name="name" value="何夜息"></constructor-arg><constructor-arg name="age" value="20"></constructor-arg></bean><bean id="user" class="com.heyexi.pojo.User"></bean>
</beans>

然后在测试类中只调用第一个对象!看看运行结果!

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Mytest
{public static void main(String[] args){//获取Spring上下文对象ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");System.out.println(applicationContext.getBean("hi"));}
}

结果显示User也被创建了!!!说明只要是弄到配置文件中,Spring都会把所有的Bean都生成出来,不管你是否调用!

Spring配置的其他配置:

别名:别名相当于换了个id名,很简单。没啥用,因为bean的name可以用空格取多个名字。

<alias name="user" alias="user2"></alias>

import:导入其他的bean配置文件。

<import resource="beans2.xml"></import>

依赖注入(DI)

什么是依赖注入?我的理解就是:

依赖:就是我们的应用程序依赖于容器,比如在某个业务中,我们需要一个连接数据库的Connection对象,但我们可以通过依赖容器,让容器给我们这个对象。

注入:就是在配置文件中,把对象的各种属性注入。

如何注入多种类型的属性?

比如,我们创建一个Javabean

package com.heyexi.pojo;import lombok.Data;import java.util.List;
import java.util.Map;@Data
public class Teacher
{private String name;private Hello hello;private String[] course;private List<String> hobby;private Map<String,String> id;
}

然后把这个注入到到配置文件中,请看配置信息:

<bean id="teacher" class="com.heyexi.pojo.Teacher"><!--普通类型通过value注入--><property name="name" value="何夜息"></property><!--引用对象类型通过ref注入--><property name="hello" ref="hi"></property><!--数组也是属于引用对象类型--><property name="course"><array><value>数据结构与算法</value><value>数据库导论</value><value>离散数学</value></array></property><!--List注入--><property name="hobby"><list><value>写代码</value><value>听音乐</value><value>跑步</value><value>弹吉他</value></list></property><!--map注入--><property name="id"><map><entry key="教师编号" value="18744"></entry><entry key="住址" value="云南"></entry></map></property>
</bean>

需要注意的也就是map的注入方式,是通过实体标签,通过给实体赋值键值对进行注入的。

然后我们在测试类中引入这个对象。

public class Mytest
{public static void main(String[] args){//获取Spring上下文对象ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");System.out.println(applicationContext.getBean("teacher"));}
}

输出结果如下:

信息: Loading XML bean definitions from class path resource [beans.xml]
Teacher(name=何夜息, hello=Hello{name='何夜息'},
course=[数据结构与算法, 数据库导论, 离散数学],
hobby=[写代码, 听音乐, 跑步, 弹吉他], id={教师编号=18744, 住址=云南})

bean的作用域(Bean Scopes)

以上就是官网的六种作用域,默认是单例模式,如下是中文版!把最后两个合并为了一个。

作用域

描述

singleton

在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值

prototype

每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()

request

每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境

session

同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境

global-session

一般用于Portlet应用环境,该运用域仅适用于WebApplicationContext环境

  1. 单例模式

    就是全局共享一个对象,不管在哪调用都是同一个对象。

<bean id="user" class="com.heyexi.pojo.User" scope="singleton"></bean>
  1. 原型模式

这个相当于每次从容器中拿的时候都是新new出来的对象。

<bean id="user" class="com.heyexi.pojo.User" scope="prototype"></bean>

Spring Beans 自动装配

除了使用可以使用配置文件中<property>来我们自己指定id获取bean外,我们也可以通过属性autowire来让spring自己去找需要的bean。

这个在SpringBoot中不是随处可见么?也没啥可以解释的了吧,一下是获取方式。

no

这是默认的设置,它意味着没有自动装配,你应该使用显式的bean引用来连线。你不用为了连线做特殊的事。在依赖注入章节你已经看到这个了。

byName

由属性名自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byName。然后尝试匹配,并且将它的属性与在配置文件中被定义为相同名称的 beans 的属性进行连接。

byType

由属性数据类型自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byType。然后如果它的类型匹配配置文件中的一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出。

constructor

类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。

autodetect

Spring首先尝试通过 constructor 使用自动装配来连接,如果它不执行,Spring 尝试通过 byType 来自动装配。

自动装配的局限性

当自动装配始终在同一个项目中使用时,它的效果最好。如果通常不使用自动装配,它可能会使开发人员混淆的使用它来连接只有一个或两个 bean 定义。不过,自动装配可以显著减少需要指定的属性或构造器参数,但你应该在使用它们之前考虑到自动装配的局限性和缺点。

只要注意byName是根据Javabean的set方法来获取的,就只需要保证xml中bean的id唯一。

byType则是根据xml中class的类型来匹配的,就不能有两个相同 class的配置文件,就会出错,需要保证bean的class唯一。

Spring的注解

首先,要使用注解需要在xml中提供注解约束

需要加入如下来句话:

xmlns:context="http://www.springframework.org/schema/context"<context:annotation-config/>

@Component注解:

这个注解的作用就是可以不再xml中配置bean了,比如我们新建一个实体类,然后在类上使用该注解。

package com.heyexi.pojo;
import org.springframework.stereotype.Component;@Component  //相当于:<bean id="dog" class="com.heyexi.pojo.User" />
public class Dog
{private String name;@Overridepublic String toString(){return "Dog{" +"name='" + name + '\'' +'}';}public String getName(){return name;}public void setName(String name){this.name = name;}
}

然后就可以在测试类中使用它了!

import com.heyexi.pojo.Dog;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Mytest
{public static void main(String[] args){//获取Spring上下文对象ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");Dog dog = (Dog)applicationContext.getBean("dog");System.out.println(dog);}
}
//输出
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7637f22: startup date [Sun Jul 12 00:22:04 CST 2020]; root of context hierarchy
7月 12, 2020 12:22:04 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
Dog{name='null'}

注意:调用时这个组件的名字就是类名的小写。

但是要使用这个组件注解,我们需要在配置文件中指定组件所在的包!就是下面这一句!

<context:component-scan base-package="com.heyexi.pojo" />

@Component有几个衍生注解,功能都一样,并没有其他特殊的功能,都是把类注入到spring容器中,只是为了区分类的作用,取了不同的名字。

  • 在dao层我们使用 @Repository注解
  • 在service层我们使用 @Service
  • 在controller层我们使用 @Controller

@Value注解:

这个注解相当于是xml配置文件中的property,就是给成员变量赋值,可以配合Comment一起使用的话,完全就可以脱离配置文件了。

@Component
public class Dog
{@Value("哈士奇")  //直接就把值给注入了private String name;输出:
信息: Loading XML bean definitions from class path resource [beans.xml]
Dog{name='哈士奇'}

要多用注解,因为在SpringBoot中基本只使用注解,代替了配置。

但是注解和配置都有自己特点:

使用配置文件的好处就是维护方便,所有的bean都统一管理,而注解维护不方便,要修改就需要去单独找。

所以,最佳的实践就是:

Xml中负责配置bean

注解(@value)负责在类中注入属性,而不再xml文件中使用属性,看着方便管理。

使用Configuration完全代替xml配置:

我们可以使用@Configuration注解,来代替xml配置文件,这个在SpringBoot中就是这么做的,我都不清楚这两个有什么区别了。

这个特别简单,就是直接生成一个类,给这个类配置@Configuration,然后在里面通过@bean注解配置bean,就会由spring来接管,如下代码:

package com.heyexi.config;import com.heyexi.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyConfig
{@Beanpublic User getUser(){return new User();}
}

我弄了一个Bean,是用来获取User对象的,然后在测试类试着拿出来。

import com.heyexi.config.MyConfig;
import com.heyexi.pojo.Dog;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Mytest
{public static void main(String[] args){ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);System.out.println(applicationContext.getBean("getUser"));}
}输出结果:
WARNING: All illegal access operations will be denied in a future release
用户被创建!
User{name='null', id=null}

可以看到,现在上下文是通过new AnnotationConfigApplicationContext("配置类的字节码")来获取的,不是通过xml,结果都是一样的。

只需要注意getBean默认是通过配置类的方法名获取的,当然也可以取别名,这个在SpringBoot笔记中写得很清楚了。

作用域可以使用@Scope注解来使用!这个还是很重要的,有时候某些实体我们需要使用单例模式,比如dao类,有时候有些实体又需要使用原型模式,这样才能拿到不同的对象。

比如我们定义为原型:

@Configuration
public class MyConfig
{@Bean@Scope("prototype")public User getUser(){return new User();}
}

然后在测试类中:

public class Mytest
{public static void main(String[] args){
//        //获取Spring上下文对象
//        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
//
//        Dog dog = (Dog)applicationContext.getBean("dog");
//        System.out.println(dog);ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);User user1 = (User) applicationContext.getBean("getUser");User user2 = (User) applicationContext.getBean("getUser");System.out.println(user1.hashCode());System.out.println(user2.hashCode());
}
输出结果:
WARNING: All illegal access operations will be denied in a future release
用户被创建!
用户被创建!
1948471365
1636506029

说明拿到的是不同的对象。

如果我们改为单例模式:输出结果为:

WARNING: All illegal access operations will be denied in a future release
用户被创建!
60292059
60292059

拿到的是同一个对象,同时可以看到构造方法都只执行了一个,说明都是同一个对象,因为是单例模式。

Spring图文详细教学笔记相关推荐

  1. 炫龙毁灭者KP2笔记本U盘重装系统方法图文详细教学

    炫龙毁灭者KP2笔记本U盘重装系统方法图文详细教学分享.炫龙毁灭者KP2笔记本是比较不错的一款游戏本.有的用户因为使用电脑的时候安装了未知安全性的文件导致系统被损坏,需要重装系统.今天我们就一起来分享 ...

  2. Python爬虫入门实战,图文详细教学,一看就懂

    同样都是程序员,为什么别人家的程序员效率那么高?因为他用 Python. 接下来我们一起来看一个入门级的Python爬虫案例是实战. 主讲内容: 1.什么是爬虫 2.浏览器的工作原理 3.爬虫的工作原 ...

  3. Linux实战教学笔记12:linux三剑客之sed命令精讲

    第十二节 linux三剑客之sed命令精讲 标签(空格分隔): Linux实战教学笔记-陈思齐 ---更多资料点我查看 1,前言 我们都知道,在Linux中一切皆文件,比如配置文件,日志文件,启动文件 ...

  4. Spring Boot 2 学习笔记(2 / 2)

    Spring Boot 2 学习笔记(1 / 2) - - - 45.web实验-抽取公共页面 46.web实验-遍历数据与页面bug修改 47.视图解析-[源码分析]-视图解析器与视图 48.拦截器 ...

  5. Linux实战教学笔记22:企业级NFS网络文件共享服务

    第二十二节 企业级NFS网络文件共享服务 标签(空格分隔): Linux实战教学笔记-陈思齐 ---本教学笔记是本人学习和工作生涯中的摘记整理而成,此为初稿(尚有诸多不完善之处),为原创作品,允许转载 ...

  6. 面试必备:高频算法题汇总「图文解析 + 教学视频 + 范例代码」之 字符串处理+动态规划 合集!

    Attention 秋招接近尾声,我总结了 牛客.WanAndroid 上,有关笔试面经的帖子中出现的算法题,结合往年考题写了这一系列文章,所有文章均与 LeetCode 进行核对.测试.欢迎食用 本 ...

  7. g5 幸存者 android,g5幸存者游戏图文详细攻略 | 手游网游页游攻略大全

    发布时间:2016-07-02 史上最坑爹的游戏9第10关失控机器人怎么过关?第十关图文详细攻略,史上最坑爹的游戏9已经在儿童节前夕正式上市了,相信喜欢这个系列游戏的玩家一定会第一时间入手的,作为一款 ...

  8. 电脑组装配置单及组装电脑图文详细教程

    在这个科技时代每个人对电脑的需求都是不一样的,由于自己配的电脑比品牌机便宜的多.而且性价比更高,很多用户都会根据自己的需求进行电脑配置选购组装.那么电脑主机的最基本配置有哪些呢?该如何完整对电脑进行组 ...

  9. Linux实战教学笔记12-linux三剑客之sed命令精讲

    第十二节 linux三剑客之sed命令精讲 标签(空格分隔): Linux实战教学笔记-陈思齐 ---更多资料点我查看 1,前言 我们都知道,在Linux中一切皆文件,比如配置文件,日志文件,启动文件 ...

最新文章

  1. text-size-adjust: 100% 有什么作用?
  2. 数据挖掘应用于流失分析的整体思路
  3. 在ddms 里面查看data/data里面的东西 不显示data/data
  4. 10分钟弄懂深度学习:卷积与特征提取
  5. 【网易MCTalk】除了低价促销、丰富品类,电商就没有新玩法了?
  6. 从PageRank到反欺诈与TextRank
  7. 大学计算机要学多久,大学刚开学要不要带电脑?很多人都很后悔,学长学姐把经验告诉你...
  8. 机器人也开始怕疼了?科学家开发无需人工干预即可自愈的机器人
  9. 200 个工具分析机器学习十年:前途未卜、工程师是核心!
  10. install google test on ubuntu
  11. C语言入门:函数递归与写法
  12. 《人月神话》读后感与读书笔记
  13. php px与rem转换,pt 与 px、em、rem 的区别与换算
  14. 按职能和级别来分,UI设计师能胜任哪些高薪岗位?
  15. 解决360浏览器自带翻译不能使用的问题
  16. BSB网络验证 易语言网络验证系统 autojs 网络验证系统 免费的卡密收费系统 账号注册系统
  17. vue脚手架项目使用element-ui
  18. iOS播放音乐与播放系统声音
  19. 奥塔在线:在win10下安装Mysql
  20. PostgreSQL与2020 PGConf.asia数据库大会值得关注!

热门文章

  1. 博彦科技JAVA笔试题及答案
  2. Meta开源JavaScript内存泄漏监测工具MemLab
  3. 双十一来临,电商舆情风险如何处理?
  4. Hadoop-3.1.3部署
  5. pythondecode函数的用法_如何使用python中的decode函数?
  6. 2017年9月英语总结
  7. 延时执行函数:前浪死在沙滩上
  8. 镜头选择基础和视觉系统
  9. loadrunner之 学习二:loadrunner函数
  10. Python:实现相等的每月分期付款算法(附完整源码)