1. Spring框架的作用

Spring框架的主要作用是创建对象和管理对象。

创建对象:类似于User user = new User();

管理对象:随时可以通过Spring框架获取对象,甚至Spring框架还能够帮我们为对象的属性进行赋值等。

2. 通过Spring框架创建对象,并获取对象

在Eclipse中创建Maven Project,在创建过程中勾上Create a simple projectGroup Id填为cn.teduArtifact Id填为spring01

如果某个项目不会被其它项目所使用,只需要保证自身能独立运行,其实Group IdArtifact Id的值是多少,并不重要。

创建成功后,先在pom.xml中添加以上配置:

<properties><java.version>1.8</java.version><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target>
</properties>

然后,对项目名称点击鼠标右键,选择Maven > Update Project以更新Maven,则当前环境会使用Java 1.8。

接下来,需要在pom.xml中添加Spring框架所需的spring-context依赖的代码:

<dependencies><!-- https://mvnrepository.com/artifact/org.springframework/spring-context --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.6.RELEASE</version></dependency>
</dependencies>

如果需要Spring管理某个类的对象,可以通过自定义的类进行配置!

例如存在需求:使得Spring框架管理Date类的对象!

先在项目的cn.tedu.spring包中创建Beans类,并且,在这个类中自定义方法,方法的返回值类型必须是Date,然后,自行在方法体中创建出Date对象并返回即可:

package cn.tedu.spring;import java.util.Date;import org.springframework.context.annotation.Bean;public class Beans {@Beanpublic Date aaa() {return new Date();}}

以上使用的包名是自定义,并不是强制要求。

以上使用的类名是自定义,并不是强制要求。

关于以上自定义的方法:

  • 应该使用public权限;
  • 返回值类型是需要Spring管理的对象所归属的类型;
  • 方法名称可以自定义;
  • 参数列表暂时为空;
  • 必须添加@Bean注解。

然后,就可以创建一个用于运行的类,加载以上类,并获取对象:

package cn.tedu.spring;import java.util.Date;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Demo {public static void main(String[] args) {// 1. 加载配置类,获取Spring容器AnnotationConfigApplicationContext ac= new AnnotationConfigApplicationContext(Beans.class);// 2. 从Spring容器中获取对象Date date = (Date) ac.getBean("aaa"); // getBean()方法的参数,就是配置对象的方法的名称// 3. 测试System.out.println(date);// 4. 关闭ac.close();}}

运行以上代码,就可以看到输出的对象!

在以上Beans类中,配置对象的方法名是aaa,在运行的Demo类中,调用getBean()方法的参数也必须是"aaa",名称必须保持一致!

通过,获取某个值的方法的名称都应该是getXxx,所以,以上Beans类中的方法应该改为:

@Bean
public Date getDate() {return new Date();
}

但是,一旦将方法名改成了getDate,运行时,调用的getBean()方法的参数也应该改成getDate,例如改成:

Date date = (Date) ac.getBean("getDate");

很显然,这个getDate表示的是一个名称,而名称应该使用名词,而不应该使用动词作为前缀!

如果要解决这个问题,可以在@Bean注解中配置参数,例如:

@Bean("date")
public Date getDate() {return new Date();
}

后续,在运行时,调用getBean()方法的参数就是@Bean注解中配置的值,例如:

Date date = (Date) ac.getBean("date");

小结:在运行时,调用的getBean()方法的参数值,默认情况下,是配置对象的方法的名称,如果配置对象的方法的@Bean注解添加了参数,则getBean()方法的参数就是@Bean注解中的参数!

其实,Spring推荐直接使用名词作为以上配置对象的方法名称,即推荐使用date作为方法名,而不是getDate作为方法名!该名词将用于getBean()方法的参数,毕竟这个方法定义好了以后,是由Spring框架去调用了,开发人员不需要自行调用该方法,为了简化代码的同时还保证getBean()代码的语义,推荐使用名词作为方法名称!

3. 由Spring管理的对象的作用域

由Spring管理的对象,在默认情况下,都是单例的!如果在配置对象的方法之前,补充添加@Scope注解,且注解参数配置为prototype时,就不是单例的了!例如:

@Bean
@Scope("prototype")
public User user() {return new User();
}

注意:Spring与单例模式是两个不同的概念!

当需要同时使用多个注解时,各注解不区分先后顺序。

由Spring管理的对象,在单例的情况下,默认是饿汉式的!如果希望调整为懒汉式的,则在配置对象方法的方法之前补充添加@Lazy注解即可:

@Bean
@Lazy
public User user() {return new User();
}

4. 由Spring管理的对象的生命周期

生命周期:某个对象从创建到最终销毁会经历的历程!

通常,需要讨论生命周期时,对应的数据类型的对象都不是由开发人员自行维护的!

被容器维护的对象,都是由容器创建对象,并在适当的时候调用其中的某些方法的!而开发人员需要做的就是“确定满足某条件的时候应该执行什么任务”!也就是说,“容器决定什么时候执行,开发人员决定执行时做什么”。

学习生命周期的意义就是“知道在什么时候需要做什么事情”!

Servlet为例,其生命周期中会有几个特殊的方法,在特定的情况下会被调用,这些就称之为生命周期方法:

  • init():当Servlet被创建对象后,立即执行,且只执行1次,该方法适合编写一些初始化相关的代码;
  • service():当接收到匹配的请求后会被调用,接收到多少次请求,就执行多少次该方法;
  • destroy():当Servlet对象即将被销毁之前执行,且只执行1次,该方法适合编写一些与结束相关的代码,例如关闭等等。

当使用Spring框架后,某些类的对象交给Spring框架来管理了,那么,这些对象在什么时候被创建、什么时候被销毁,及创建过程和销毁过程中需要执行某些代码,对于开发人员来说,一定程度上是不可控的!

Spring框架允许用户在类中自定义最多2个方法,分别表示“初始化方法”和“销毁方法”,并且,Spring框架会在创建对象之后自动调用初始化方法,会在销毁对象之前调用销毁方法!关于方法的定义:

  • 访问权限:应该使用public权限;
  • 返回值类型:使用void
  • 方法名称:自定义;
  • 参数列表:空。

例如,在User类中自定义2个生命周期方法:

public void init() {System.out.println("User.init()");
}public void destroy() {System.out.println("User.destroy()");
}

然后,在配置对象的方法之前的@Bean注解中配置这2个方法作为生命周期方法:

@Bean(initMethod="init", destroyMethod="destroy")
public User user() {return new User();
}

5. 通过组件扫描使得Spring管理类的对象

假设存在User类,需要被Spring框架创建并管理对象,则,必须先明确User类所在的包,然后,在用于运行的类Demo中,在AnnotationConfigApplicationContext的构造方法中,将包名作为构造方法的参数,例如:

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext("cn.tedu.spring");

以上代码则表示“组件扫描”,当执行时,Spring框架会扫描指定的包中所有的内容,并且,自动创建各组件的对象并进行管理!

当然,并不是所有的类都是“组件”,如果要标识某个类是“组件”,必须在类的声明之前添加@Component注解!例如:

package cn.tedu.spring;import org.springframework.stereotype.Component;@Component
public class User {}

后续,从Spring容器中获取对象时,默认情况下,将类名的首字母改为小写,作为Bean的名称,用于调用getBean()方法的参数,例如:

User user = ac.getBean("user", User.class);

关于Bean的名称,如果类名首字母是大写,且第2个字母是小写,例如UserStudent,则Bean的名称就是将首字母改为小写即可,也就是userstudent!如果不满足该条件,例如类名是teacherIUserDao,则Bean的名称就是类的名称!

当然,Spring框架也允许自定义Bean的名称,只要将自定义的名称配置在@Component注解参数中即可,例如:

package cn.tedu.spring;import org.springframework.stereotype.Component;@Component("stu")
public class Student {}

则以上类的对象被Spring管理时,Bean的名称就是"stu",后续,调用getBean()方法获取对象时,也必须使用这个名称来获取对象:

Student stu = ac.getBean("stu", Student.class);

【附】1. 单例模式

单例模式,是设计模式中的一种。

单例模式,其特点是:被设计为单例的类型,在同一时间内,该类型的对象只会存在1个!

假设存在King类:

public class King {}

作为一个普通的类,是可以在类的外部随意创建对象的,例如:

King k1 = new King();
King k2 = new King();
King k3 = new King();

因为在King类中,没有声明构造方法,则编译器会自动的添加默认构造方法,也就是公有的、无参数的构造方法,所以,在类的外部才可以随意创建对象!以上代码中就创建了3个King类型的对象!

如果要实现单例,首先,就不能允许随意创建对象,可以显式的添加构造方法,并将其私有化,避免外部随意访问,例如:

public class King {private King() {}
}

一旦显式的添加了构造方法,编译器就不会再自动添加构造方法了,则在类的外部,将不可以再执行King k1 = new King();这类的代码了!

使用了私有的构造方法,并不影响在类的内部使用该构造方法,为了保证在类的外部依然可以获取类的对象,则可以:

public class King {private King() {}public King getInstance() {return new King();}
}

同时,为了保证“多次获取时,获取到的都是同一个对象”,则不能反复在方法中创建对象,而是改为:

public class King {private King king = new King();private King() {}public King getInstance() {return king;}
}

改为这样以后,无论执行多少次getInstance()方法,该方法返回的都是同一个king变量,而该变量的值只是在类被加载时赋值了1次而已,就实现了单例的效果!

当然,以上代码是矛盾的!因为,如果要调用getInstance()方法,必须先有King类型的对象,而得到King类型对象的唯一途径就是调用getInstance()方法!也就是说:不调用getInstance()方法就无法得到对象,但是,调用方法之前又必须有对象!

为了解决这个问题,可以为getInstance()方法添加static修饰符,则通过类名.方法名()的格式就可以调用方法了,不需要事先获取对象!同时,基于“被static修饰的成员不可以直接访问没被static修饰的成员”的原则,所以,全局的private King king = new King();也需要添加static修饰符:

public class King {private static King king = new King();private King() {}public static King getInstance() {return king;}
}

至此,简单的单例模式代码就完成了,后续,需要获取King类型的对象时,只能通过King.getInstance()得到对象,而该方法每次返回的都是同一个对象!

严格来说,以上单例模式的设计是“饿汉式”的,可以看到,在类被加载时,就直接创建了King类的对象,此时,也许并不需要获取对象,但是,也创建好了 ,后续,当需要对象时,直接获取即可!另外,还有“懒汉式”的单例模式,其特点就是“不到逼不得已,不创建对象”!其基础代码例如:

public class King {private static King king;private King() {}public static King getInstance() {if (king == null) {king = new King();}return king;}
}

以上代码是多线程不安全的!为了解决这个问题,可以将以上代码块添加互斥锁,例如:

public class King {private static King king;private King() {}public static King getInstance() {synchronized("java") {if (king == null) {king = new King();}}return king;}
}

一旦添加了锁,就会导致每次调用getInstance()方法时都会先锁定代码再执行,效率偏低,为了解决该问题,还可以:

public class King {private static King king;private King() {}public static King getInstance() {if (king == null) { // 判断是否有必须加锁,如果没有该判断,则效率可能偏低synchronized("java") {if (king == null) { // 判断是否有必须创建对象,如果没有该判断,则可能创建多个对象king = new King();}}}return king;}
}

以上,就是完整的懒汉式的单例模式!

小结:单例模式的特点就是“单一实例”,表现为“同一时间内,某个类的对象只有1个”!单例模式分为“饿汉式”和“懒汉式”这2种,前者是“早早的创建出对象,随时可以获取”,后者是“不到逼不得已不会创建对象”!

Spring框架学习day_01: 框架配置方式/ 管理对象的作用域/ 生命周期/ 组件扫描/ 单例模式:“懒汉式“,“饿汉式“相关推荐

  1. java学习之单例模式(饿汉式与懒汉式)

    ---恢复内容开始--- 设计模式:解决某一类问题最行之有效的方法 java中有23种设计模式 今天学习其中一种:单例设计模式:解决一个类在内存只存在一个对象 想要保证对象唯一. 1.为了避免其他程序 ...

  2. SpringMVC框架 学习DAY_01:框架概括 / 简易应用 / 核心执行流程图 /在框架下显示HTML模板页面/ 接受请求

    1. SpringMVC框架的作用 MVC = Model(数据模型) + View(视图) + Controller(控制器) SpringMVC框架主要解决了接收请求与处理响应的问题,也可以认为是 ...

  3. 【无标题】单例模式的两种创建方式:饿汉式和懒汉式

    这里写自定义目录标题 单例模式的两种创建方式:饿汉式和懒汉式 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题,有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂 ...

  4. Spring Bean的三种配置方式

    目录 一.传统的XML配置方式 二.基于java注解的配置 三.基于类的Java Config 正文 Spring Bean有三种配置方式: 传统的XML配置方式 基于注解的配置 基于类的Java C ...

  5. 框架学习——WCF框架

    框架学习--WCF框架 什么是WCF .NET平台下,有很多分布式技术 WCF 快速搭建一个WCF程序 1.ABC概念 2.如何定义WCF项目 参考资料 什么是WCF .NET平台下,有很多分布式技术 ...

  6. Spring定时任务@Scheduled注解使用配置方式(cron表达式、fixedRate和fixedDelay)

    Spring定时任务@Scheduled注解使用配置方式(cron表达式.fixedRate和fixedDelay) 序言: 个人推荐一个很方便的在线Cron生成器(网页版):https://qqe2 ...

  7. 生命周期组件框架:带有多状态机的单实现类

    ServiceOrder生命周期元数据 @StateMachine public interface ServiceOrderLifecycleMeta extends OrderLifecycleM ...

  8. 【学习笔记】【C++整理A】【总】单例模式-饿汉式、懒汉式;

    文章目录 一.语言分类: 三.基础A:- 函数重载.默认参数.extern "C".重复包含 1.函数重载 2.默认参数 3.extern "C" 4.防止重复 ...

  9. IOC操作Bean管理XML方式(bean 的生命周期)

    目录 IOC操作Bean管理XML方式(bean 的生命周期) 1.bean 的生命周期(在单例模式下的生命周期) (1)通过构造器创建 bean 的实例(执行类中无参构造方法去创建对象) (2)为 ...

最新文章

  1. Python黑客编程基础3网络数据监听和过滤
  2. ios 边录音边放_关于Android和iOS系统OneNote支持边录音边记笔记的需求和建议
  3. PCM - partner channel management 的数据库表介绍
  4. mongodb副本集_设置MongoDB副本集分为4个步骤
  5. FICO蓝图设计-专题方案-财务组织架构
  6. 【小梅哥SOPC学习笔记】系统时钟的使用
  7. 2018-2019-2 网络对抗技术 20165227 Exp4 恶意代码分析
  8. 大学python笔记整理_python 笔记整理
  9. 《Java 核心技术 卷1》 笔记 第八章 事件处理
  10. React之Hook(四)——使用 Effect Hook
  11. 手把手实战机器学习系列: 随机森林
  12. 前端vue视频vue-video-player插件总结知识点案例(带源码)
  13. 第一步PHP开发环境搭建
  14. Mozilla Firefox 全版本下载
  15. Giv Svn Branch 操作
  16. echo 多行_【庭审现场】利用注销公司诈骗 多行不义必自毙_政务_澎湃新闻
  17. cms可视化编辑php,AyaCMS与We7CMS可视化编辑模板功能对比
  18. [WordPress] 隐藏 Featured Image 新手非程序方法
  19. 【重要征稿】IEEE 2022年网络、计算机和通信国际学术研讨会(ISNCC2022)
  20. 平行束投影数据的仿真

热门文章

  1. 一个基于POI的通用excel导入导出工具类的简单实现及使用方法
  2. 计算机实现减法学习心得
  3. NET仿微信Oauth2.0
  4. Oracle性能监控脚本
  5. php session函数
  6. LeetCode-Unique Binary Search Trees
  7. 浅谈Python Web的五大框架
  8. vegas pro 15解决导入的视频和音频有噪声问题,亲测可行
  9. Keil 5出现Error: L6218E: Undefined symbol解决方法
  10. linux 线程操作问题undefined reference to ‘pthread_create‘的解决办法(cmake)