跟我一起学Spring(一)

什么是Spring?

开篇前,分享阿里云服务器一折,89/年,229/3年,比学生服务器9.9每月还便宜,买来送自己,送女朋友,马上过年在适合不过了,买来搭建个项目给面试官看也香,还可以熟悉技术栈(老用户用家人的账户买就好了,我用我女朋友的账号)。←点击或者点击链接购买↓

阿里云服务器一折活动地址:阿里云.云小站
腾讯云服务器一折活动地址:腾讯云·年末有礼

Spring在我们日常开发项目中可以说是基本上离不开了,而Spring从2.x版本到5.x版本,由单独IOC以及AOP发展到现在的一套spring生态(springcloud),受到广大程序员的青睐。
维基百科解释:

Spring框架是 Java平台的一个开源的全栈应用程序框架和控制反转容器实现,一般被直接称为Spring。该框架的一些核心功能理论上可用于任何Java 应用,但Spring 还为基于Java企业版平台构建的Web 应用提供了大量的拓展支持。

自己的理解:

  • Spring它是一个轻量级的框架,主要用于开发Java应用。
  • Spring是一款软件的半成品,框架目的本身是简化Java企业级应用开发。

Spring能解决哪些问题?

  1. 从面向对象(静态)角度思考(面向对象分析构建)
  • 对象的创建(在没框架之前,我们创建对象都是通过手动进行new出来,而Spring的IOC就能帮我们解决)
  • 对象的管理(对象都是存储在内存的堆中,倘若对对象没有进行科学的管理则可以造成内存泄漏问题,多个对象内存泄漏就会导致内存溢出(创建对象的速度大于对象销毁速度)问题)
  • 对象依赖注入(对象由spring来创建,需要对象使用的时候,spring将对象赋值给应用程序的过程称为依赖注入,对象与对象之间是存在依赖关系的)
  1. 从面向切面(动态)的角度思考(不改变原有代码的前提下,去扩展新的功能)
  • 对象的功能扩展(业务需求的不断变更修改)
  1. 从项目架构的角度分析
  • MVC分层架构,mould、视图层、控制层
  1. 面向服务(粒度)的角度思考(一个系统由多个微服务构建,分布式部署)
  • 对象的粒度问题(微服务)

spring的核心组件?

  • IOC容器(控制反转器):对象的创建、对象的存储、对象的注入
  • WEB组件(重点解决MVC中细节问题–>处理请求,处理响应)
  • AOP组件(重点解决对象扩展问题)
  • Data组件(整合jdbc,整合mybatis)

spring核心架构?

Spring最初的目标就是要整合一切优秀的资源,如何对外提供一个统一的服务。
spring的架构图(spring4.0):
在这里插入图片描述

spring IOC简介

Spring 中有一个核心容器,这个容器我们通常称之为IOC容器,这个容器最核心功能就是控制反转。这个容器负责对象的创建,对象的存储(map),对象的管理(依赖查找,依赖注入)。

IOC容器如何实现?

1.1 容器如何知道创建哪些对象
通过xml或者注解的方式描述要创建的对象
1.2 容器如何构建这些类的对象
通过反射技术,Class.forName(" ")
1.3 容器如何存储对象
通过Map容器存储
1.4 IOC最大优势和劣势?
优势:

  • 无需从新编译,只需要配置
  • 更好的使用内存,防止内存泄漏(通过Map进行存储)
  • 更好的解耦和(接口与接口之间的调用,如controller调service接口)

劣势:

  • 构建对象过程变复杂(从原本的new变成需要添加注解和配置文件写容器存储等…)
  • 对象结构可读性降低了(如:接口调用接口时不知调用的是哪个实现类)

spring IOC构建

<beans default-lazy-init="true">
	<bean id="helloService" class="com.beans.HelloService">
<beans>
public class HelloService{
	public void sayHello(){
		System.out.println("hello spring");
	}
}
public static void main(String[] args){
	/** 传统方式 */
	HelloSerivce hello = new HelloService();
	hello.sayHello();

	/** Spring IOC方式 */
	1.初始化spring容器(此时不会调用该类的构造方法,也就是不会创建对象,将beans里面的default-lazy-init="true"延迟加载去除,则会在初始化容器时创建该对象)
	ApplicationContext app = new ClassPathXmlApplicationContext("spring-configs.xml");
	//ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-configs.xml");
	2.获取Bean对象
	HelloService service = app.getBean("helloService", HelloService.class);
	3.使用Bean对象
	service.sayHello();
	4.释放资源
	//context.close();
}

Spring Bean对象的基本使用

1.1 Bean 对象的配置

在软件应用中由spring管理的所有对象都称之为bean。我们自己创建的类,假如需要spring管理,首先对这个类进行配置,常用的配置有两种,一种基于xml配置,另一种基于注解进行配置。

基于xml方式对象bean对象进行配置时,首先需要在spring的核心配置文件中,使用bean标签对象bean类型进行声明,借助id或者name属性指定bean的唯一标识,通过class属性指定bean的具体类型(类名必须写全类路径名)

<bean id="helloService" class="com.beans.HelloService"/>
<!-- 或者 -->
<bean name="helloService" class="com.beans.HelloService"/>
1.2 Bean 对象的构建
  1. 通过构造方法
  2. 通过静态工厂方法(例如:Calendar的getInstance静态方法)
  3. 通过实例方法(例如:通过Calendar对象的getTime方法获取Date对象)
    【注意】:以上无论通过哪种哪种方式构建对象,底层都会用到反射
    spring-config.xml
<!-- 1.直接通过类的构造方法构建对象 -->
<bean id="date" class="java.util.Date"/>
<!-- 2.该bean无法构建初始化对象,因为这个类是抽象方法 -->
<bean id="calendar" class="java.util.Calendar"/>
<!-- 正确写法:通过该类的getInstance静态工厂方法构建对象 -->
<bean id="calendar" class="java.util.Calendar" factory-method=“getInstance”/>
<!-- 3.通过Calendar对象的getTime方法获取date对象。calendar表示引用上面的calendar bean, getTime方法表示调用Calendar对象的getTime方法 -->
<bean id="date" factory-bean="calendar" factory-method="getTime"/>

单元测试test

@junit
public class test{
	private ClassPathXmlApplicationContext app;
	@Before
	public void init(){
		app = new ClassPathXmlApplicationContext("spring-config.xml")
	}
	@Test
	public void testCalendar(){
		//Calendar cal = Calendar.getInstance();
		Calendar cal = app.getBean("calendar", Calendar.calss);
	}
	@Test
	public void testDate(){
		Date date = app.getBean("date", Date.class)
	}
	@After
	public void closeTest(){
		app.close();
	}
}
1.3 Bean 对象的作用域

在spring容器中管理Bean对象,可以声明时通过scope属性或相关注解指定其作用域,最常见是singleton,prototype,其含义如下:

  1. singleton:这个作用域标识的对象具备全局唯一性(系统默认)
  2. prototype:这个作用域标识的对象每次获取都会创建新的对象
<!-- 此时在测试类中getBean获取该对象时,只会调用该类的一次构造方法 -->
<bean id="helloService" class="com.beans.HelloService" scope="singleton"/>
<!-- 此时在测试类中getBean获取该对象时,会调用该类的多次构造方法 -->
<bean id="helloService" class="com.beans.HelloService" scope="prototype"/>

HelloService类

public class HelloService{
	public HelloService(){
		System.out.println("helloService()")
	}
}

单元测试test

@Test
publilc void testHelloService(){
	HelloService helloService = app.getBean("helloService", HelloService.class);
	helloService = app.getBean("helloService", HelloService.class);
}

控制台输出
当bean的scope=“singleton”

helloService()

当bean的scope=“prototype”

helloService()
helloService()
1.4 spring Bean的生命周期

在spring框架应用中,所有的bean对象都有生命周期,所谓bean对象的生命周期是指Bean对象的创建、初始化、服务、销毁这个过程。
在spring配置文件中可以通过init-method,destory-method属性指定bean对象的生命周期。
在spring应用由spring创建的对象是否有spring销毁,还取决于作用域的配置。例如:

  1. singleton作用域的对象可以在容器关闭是销毁。
  2. prototype作用域对象可以有容器创建对象,初始化对象,但不负责销毁。
    spring-config.xml
<!-- 当scope=“singleton时,destory方法不会执行,因为对象是唯一的,只有将容器close后才会执行destory方法” -->
<bean id="helloService" class="com.beans.HelloService" scope="singleton" init-method="init" destroy-method="destory"/>

HelloService类

public class HelloService{
	//getbean获取对象时执行
	public HelloService(){
		System.out.println("helloService()")
	}
	//创建对象之后执行
	public void init(){
		System.out.println("init()")
	}
	//服务
	public void sayHello(){
		System.out.println("sayHello()")
	}
	//销毁对象时候执行
	public void destory(){
		System.out.println("destory()")
	}
}

单元测试类

@Test
publilc void testHelloService(){
	HelloService helloService = app.getBean("helloService", HelloService.class);
	helloService.sayHello();
}
@After
public void close(){
	//当scope=“singleton”时,只有关闭资源,才能调用HelloService的destory()方法
	//app.close();
}

控制台输出

helloService()
init()
sayHello()
1.5 Bean 对象的延迟加载

在spring应用中,容器初始化时,默认会构建所有由spring管理的bean对象.。但假如这些对象长时间不使用还占用着内存就会造成一定的资源浪费,为了解决这种问题,spring中提供了一种延迟加载机制,通过这种机制来提高系统资源的有效使用。
Spring中的延迟加载需要通过bean元素中的 lazy-init 属性或者beans的default-lazy-init=“true”属性进行设置。两者应用的不同点:

  1. lazy-init:应用在bean标签中,指定某个bean标签的加载策略(局部)。
  2. default-lazy-init:应用在beans标签中,指定所有bean标签的加载策略(全局)。
<beans default-lazy-init="true">
	<bean id="helloService" class="com.beans.HelloService">
<beans>
<!-- 或者 -->
<beans>
	<bean id="helloService" class="com.beans.HelloService" lazy-init="true">
<beans>

【思考】

  1. 什么叫延迟加载?
    什么时候使用什么时候加载。
  2. 延迟加载要解决什么问题呢?
    内存的使用问题。
    3.对象延迟加载的应用场景?
    当一个对象占用的内存比较大,而且使用频率比较少。
    如:int array = new int[4096]
  3. 连接池对象是否适合延迟加载?
    个人认为:不适合。
    因为在需要使用的时候才去创建连接池,创建对象,分配内存等操作,性能慢,用户访问资源时慢,体验不好。

看到最后的都是人才,喜欢记得点赞哦!不然白嫖我了❤

发布了15 篇原创文章 · 获赞 32 · 访问量 6334

猜你喜欢

转载自blog.csdn.net/CSDN_Qiang17/article/details/89913721