Spring

  • 引言
    • 什么是 Spring?
    • 工厂设计模式
      • 简单工厂的设计
      • 通用工厂的设计
      • 通用工厂的使用方式
  • 第一个 Spring 程序
    • 环境搭建
    • Spring 的核心API
    • 程序开发
    • 细节分析
      • Spring 工厂的相关的方法
      • 配置文件中的细节
    • Spring工厂的底层实现原理(简易版)
    • 思考
  • Spring5.x 与 日志框架 的整合

更多内容请查看笔记目录:【Spring 5.x】学习笔记汇总

引言

EJB(Enterprise Java Bean)存在的问题EJB 是重量级的框架

  1. 运行环境苛刻
  2. 代码移植性差

什么是 Spring?

Spring是⼀个轻量级的 JavaEE 解决方案,整合众多优秀的设计模式。

什么是轻量级?

  1. 对于运行环境是没有额外要求的;
    开源:tomcat、resion、jetty
    收费:weblogic、websphere
  2. 代码移植性高:不需要实现额外接口。

JavaEE 的解决方案

整合设计模式:

  1. 工厂
  2. 代理
  3. 模板
  4. 策略

什么是设计模式?

  • ⼴义概念:面向对象设计中,解决特定问题的经典代码。
  • 狭义概念:GOF4人帮定义的23种设计模式:工厂、适配器、装饰器、门面、代理、模板…

工厂设计模式

什么是工厂设计模式?

  1. 概念:通过工厂类,创建对象;

    User user = new User();
    UserDAO userDAO = new UserDAOImpl();
    
  2. 好处:解耦合
    耦合:指定是代码间的强关联关系,⼀方的改变会影响到另⼀方;
    问题:不利于代码维护;
    简单:把接口的实现类,硬编码在程序中;

    UserService userService = new UserServiceImpl();
    

简单工厂的设计

package com.baizhiedu.basic;import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;public class BeanFactory {private static Properties env = new Properties();static{try {//第一步 获得IO输入流InputStream inputStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");//第二步 文件内容 封装 Properties集合中 key = userService value = com.baizhixx.UserServiceImplenv.load(inputStream);inputStream.close();} catch (IOException e) {e.printStackTrace();}}/*对象的创建方式:1. 直接调用构造方法 创建对象  UserService userService = new UserServiceImpl();2. 通过反射的形式 创建对象 解耦合Class clazz = Class.forName("com.baizhiedu.basic.UserServiceImpl");UserService userService = (UserService)clazz.newInstance();*/public static UserService getUserService() {UserService userService = null;try {//com.baizhiedu.basic.UserServiceImplClass clazz = Class.forName(env.getProperty("userService"));userService = (UserService) clazz.newInstance();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return userService;}public static UserDAO getUserDAO(){UserDAO userDAO = null;try {Class clazz = Class.forName(env.getProperty("userDAO"));userDAO = (UserDAO) clazz.newInstance();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return userDAO;}}

配置文件 applicationContext.properties:

# Properties 集合 存储 Properties文件的内容
# 特殊Map key=String value=String
# Properties [userService = com.baizhiedu.xxx.UserServiceImpl]
# Properties.getProperty("userService")userService = com.baizhiedu.basic.UserServiceImpl
userDAO = com.baizhiedu.basic.UserDAOImpl

通用工厂的设计

问题:简单工厂会存在大量的代码冗余。

通用工厂的代码:

package com.baizhiedu.basic;import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;public class BeanFactory {private static Properties env = new Properties();static{try {//第一步 获得IO输入流InputStream inputStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");//第二步 文件内容 封装 Properties集合中 key = userService value = com.baizhixx.UserServiceImplenv.load(inputStream);inputStream.close();} catch (IOException e) {e.printStackTrace();}}/*key 小配置文件中的key [userDAO,userService]*/public static Object getBean(String key){Object ret = null;try {Class clazz = Class.forName(env.getProperty(key));ret = clazz.newInstance();} catch (Exception e) {e.printStackTrace();}return ret;}}

配置文件 applicationContext.properties:

# Properties 集合 存储 Properties文件的内容
# 特殊Map key=String value=String
# Properties [userService = com.baizhiedu.xxx.UserServiceImpl]
# Properties.getProperty("userService")userService = com.baizhiedu.basic.UserServiceImpl
userDAO = com.baizhiedu.basic.UserDAOImpl

通用工厂的使用方式

  1. 定义类型 (类)
  2. 通过配置文件的配置告知工厂
    applicationContext.propertieskey = value
  3. 通过工厂获得类的对象
    Object ret = BeanFactory.getBean("key");

总结
Spring本质:工厂 ApplicationContext (applicationContext.xml)

第一个 Spring 程序

环境搭建

依赖查询网站:https://mvnrepository.com/;

配置 Spring 的 jar 包:

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

Spring 的配置文件:

  1. 配置文件的放置位置:任意位置,没有硬性要求;
  2. 配置文件的命名 :没有硬性要求,建议:applicationContext.xml

思考:日后应用 Spring 框架时,需要进行配置文件路径的设置。

Spring 的核心API

ApplicationContext

  • 作用:Spring 提供的 ApplicationContext 这个工厂,用于对象的创建;
    好处:解耦合
  • ApplicationContext 是接口类型;
    接口:屏蔽实现的差异
    非 web 环境 (main junit) :ClassPathXmlApplicationContext
    web 环境 :XmlWebApplicationContext
  • 重量级资源:
    ApplicationContext 工厂的对象占用大量内存。
    不会频繁的创建对象 ,⼀个应用只会创建⼀个工厂对象。
    A pplicationContext 工厂:⼀定是线程安全的(多线程并发访问)。

程序开发

  1. 创建类型:Person.java
public class Person {}
  1. 配置文件的配置:
<?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="person" class="com.yusael.basic.Person"/></beans>
  1. 通过工厂类,获得对象
/*** 用于测试Spring的第一个程序*/
@Test
public void test() {// 1、获取spring的工厂ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");// 2、通过工厂类获得对象Person person = (Person)ctx.getBean("person");System.out.println(person);
}

细节分析

名词解释:Spring 工厂创建的对象,叫做 bean 或者 组件 (componet);

Spring 工厂的相关的方法

getBean:传入 id值 和 类名 获取对象,不需要强制类型转换。

// 通过这种方式获得对象,就不需要强制类型转换
Person person = ctx.getBean("person", Person.class);
System.out.println("person = " + person);

getBean:只指定类名,Spring 的配置文件中只能有一个 bean 是这个类型。

// 使用这种方式的话, 当前Spring的配置文件中 只能有一个bean class是Person类型
Person person = ctx.getBean(Person.class);
System.out.println("person = " + person);

getBeanDefinitionNames:获取 Spring 配置文件中所有的 bean 标签的 id 值。

// 获取的是Spring工厂配置文件中所有bean标签的id值  person person1
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {System.out.println("beanDefinitionName = " + beanDefinitionName);
}

getBeanNamesForType:根据类型获得 Spring 配置文件中对应的 id 值。

// 根据类型获得Spring配置文件中对应的id值
String[] beanNamesForType = ctx.getBeanNamesForType(Person.class);
for (String id : beanNamesForType) {System.out.println("id = " + id);
}

containsBeanDefinition:用于判断是否存在指定 id 值的 bean,不能判断 name 值

// 用于判断是否存在指定id值的bean,不能判断name值
if (ctx.containsBeanDefinition("person")) {System.out.println(true);
} else {System.out.println(false);
}

containsBean:用于判断是否存在指定 id 值的 bean,也可以判断 name 值

// 用于判断是否存在指定id值的bean,也可以判断name值
if (ctx.containsBean("p")) {System.out.println(true);
} else {System.out.println(false);
}

配置文件中的细节

如果 bean 只配置 class 属性:

<bean class="com.yusael.basic.Person"></bean>
  • 会自动生成一个 id,com.yusael.basic.Person#1
    可以使用 getBeanNamesForType 验证。
  • 应用场景:
    如果这个 bean 只需要使用⼀次,那么就可以省略 id 值;
    如果这个 bean 会使用多次,或者被其他 bean 引用则需要设置 id 值;

name 属性:

  • 作用:用于在 Spring 的配置文件中,为 bean 对象定义别名(小名)
  • name 与 id 的相同点:
    • ctx.getBean("id")ctx.getBean("name") 都可以创建对象;、
    • <bean id="person" class="Person"/><bean name="person" class="Person"/> 等效;
  • name 与 id 的区别:
    • 别名可以定义多个,但是 id 属性只能有⼀个值;
    • XML 的 id 属性的值,命名要求:必须以字母开头,可以包含 字母、数字、下划线、连字符;不能以特殊字符开头 /person
      XML 的 name 属性的值,命名没有要求,/person 可以。
      但其实 XML 发展到了今天:ID属性的限制已经不存在,/person也可以。

Spring工厂的底层实现原理(简易版)

思考

问题:未来在开发过程中,是不是所有的对象,都会交给 Spring 工厂来创建呢?

回答:理论上是的,但是有特例 :实体对象(entity) 是不会交给Spring创建,它由持久层框架进行创建。

Spring5.x 与 日志框架 的整合

Spring 与日志框架进行整合,日志框架就可以在控制台中,输出Spring框架运行过程中的⼀
些重要的信息。
好处:便于了解Spring框架的运行过程,利于程序的调试。

默认日志框架
Spring 1.x、2.x、3.x 早期都是基于commonslogging.jar
Spring 5.x 默认整合的日志框架 logback、log4j2

Spring 如何整合日志框架?
Spring5.x 整合 log4j:

  1. 引⼊ log4j.jar 包;
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version>
</dependency>
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>
  1. 引⼊ log4.properties 配置文件;
# resources文件夹根目录下
### 配置根
log4j.rootLogger = debug,console### 日志输出到控制台显示
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

【Spring 工厂】工厂设计模式、第一个Spring程序细节分析、整合日志框架相关推荐

  1. Spring学习笔记:第一个Spring Boot程序HelloWorld

    Spring学习笔记:第一个Spring Boot程序HelloWorld 一.跟着 Spring 了解技术趋势 1.看看 Spring 5.x 的改变暗示了什么 2.Spring Boot 和 Sp ...

  2. spring boot:从零开始搭建一个项目 - day 4 控制台输出日志美化 + swagger2

    spring boot:从零开始搭建一个项目 - day 4 控制台输出日志美化 + swagger2 一.logback.xml配置日志美化 二.集成swagger2 1.引入依赖 2.编写配置文件 ...

  3. Spring Boot(5)一个极简且完整的后台框架

    一个完整的极简后台框架,方便做小项目的时候可以快速开发. 这里面多贴图片和代码,做个参考吧,代码可以下载下来自己看看,里面这套后台模板不错,喜欢的拿去. 先放几张图 项目介绍 SpringBoot,我 ...

  4. idea log 不输出error_还在使用console.log()吗?Bunyan:一个简单易用的JS日志框架

    Bunyan是一个简单易用的JS日志框架,可以工作在多种环境下,这里以Nodejs为例说明Bunyan的基本用法.是时候替换console.log的写法了. 安装 npm install --save ...

  5. android 日志框架封装,FLog: 一个基于函数组合的Android日志框架,拥有极简的结构和极高的灵活性、扩展性...

    FLog 一个基于函数组合的Android日志框架,拥有极简的结构和极高的灵活性.扩展性 下载 在根目录下的build.gradle中添加jitpack.io的maven地址 allprojects ...

  6. 使用 Spring Boot CLI 运行第一个Spring boot程序

    简介 Spring Boot CLI是Spring Boot的命令行界面.它可以用来快速启动Spring.  它可以运行Groovy脚本.  Spring Boot CLI是创建基于Spring的应用 ...

  7. Spring Boot (1) 构建第一个Spring Boot工程

    Spring boot简介 spring boot是spring官方推出的一个全新框架,其设计目的是用来简化新spring应用的初始搭建以及开发过程. Spring boot特点 1.化繁为简,简化配 ...

  8. spring日志报错提醒_Spring Boot 2.x : 整合日志框架 Log4j2

    日志框架概述 在一个 web 项目建设中,如果说第一件事是 Spring 框架的搭建,那么第二件事就是日志框架的搭建,线上 web 项目的日志可能是我们了解项目运行的唯一方式. 常用日志框架 java ...

  9. Spring整合日志框架Log4j2

    对于一款软件而言,日志记录都是十分重要的.它不仅能够监控程序的运行情况,周期性的记录到文件中,还能够跟踪程序中代码的运行轨迹,向文件或控制台打印代码的调试信息.当程序出现错误时,日志记录可以帮助开发人 ...

最新文章

  1. 第 5 章 Spring Boot
  2. dictionary changed size during iteration
  3. 深入netty源码解析之一数据结构
  4. 方正魏新:我们走的产业路线比联想高端
  5. IDEA中进行SpringBoot整合spring-ws开发webservice接口后期要修改xsd文件流程
  6. C语言数组的深入理解
  7. 移动应用安全初创企业Seworks获820万美元A轮融资
  8. pytorch from_numpy
  9. php ajax国家时间,php ajax 实时显示时间
  10. Halcon内参外参畸变矫正
  11. jQuery学习教程 基础篇 归档
  12. React-Native 仿喜马拉雅APP项目笔记(多环境配置 项目配置路径 堆栈式导航)
  13. Stream Processing With Flink (7) 状态算子和用户函数
  14. spawn xelatex ENOENT的问题
  15. Golang对中文汉字进行拼音排序
  16. 怎么将自己的头像p到特定的背景图_怎么把自己的头像和背景分离出来:用ps抠图...
  17. iOS 防止录屏和截屏的监听
  18. java订单到期自动取消_订单自动过期实现方案
  19. 腾讯提出共享 AI,抢先布局游戏与多媒体 AI,首秀同声传译
  20. DB、DBMS、SQL分别是什么,有什么关系?

热门文章

  1. 眼下很多创业者之所以会创业失败
  2. 使人无条件相信你的5个策略
  3. 任何时间都是送给我们的最好礼物
  4. 你觉得一个128g主力机用几年会到非换不可的程度?
  5. 自学dapp开发资料
  6. 人工智能及其体系结构_一些复制体系结构错误及其解决方案
  7. 设计模式:观察者(Observer)模式
  8. MySQL数据库储存引擎Inoodb一--记录储存结构
  9. [LeetCode] 144. Binary Tree Preorder Traversal Java
  10. ionic中定义路由的问题