一、Spring前言

讲Spring之前先写段代码,体会一下Java创建对象的方式,这块你理解了对后面有好处!

1、原始时代-new对象

直接new创建对象,代码如下:

//User.java
package com.ty.bean; public class User {
private String username;
private String password; /**
* 省略有参无参构造,getter/setter方法
*/
}
//UserDao.java
public interface UserDao {
void getUser(String username,String password);
} //UserDao的实现类UserDaoImpl.java
public class UserDaoImpl implements UserDao {
@Override
public void getUser(String username, String password) {
System.out.println("用户名:"+username+"\t密码:"+password);
}
}
//UserService.java
public interface UserService {
void getUser(String username,String password);
} //UserService的实现类UserServiceImpl.java
public class UserServiceImpl implements UserService {
private UserDao userDao= new UserDaoImpl();
@Override
public void getUser(String username, String password) {
userDao.getUser(username,password);
}
}

正常来讲这里还需要写一个UserController,但是我们只是测试,所以就写一个TestUser类

public class TestUser {
@Test
public void test(){
UserService userService=new UserServiceImpl();
userService.getUser("jack","root");
}
}

这是之前学习经常写的方式用来完成某种功能,service层调用dao层;UserService的实现类调用UserDao的实现类。想象一下:如果我们业务更改了,增加了一个UserService的实现类BUserServiceImpl,使用的时候代码就要变成这样

public class TestUser {
@Test
public void test(){
//UserService userService=new UserServiceImpl();
UserService userService=new BUserServiceImpl();
userService.getUser("jack","root");
}
}

这就是所谓的耦合,调用的时候要修改代码,即直接new , 显然不符合面向对象的设计原则---------开闭原则

2、过渡时代-工厂

工厂方式,再原来的代码修改一下

先创建一个BeanFactory.java文件

//创建工厂类,BeanFactory.java
public class BeanFactory {
public static UserService getUser(){
return new UserServiceImpl();
}
}

这样使用的时候就变成这样

 @Test
public void test(){
UserService userService= BeanFactory.getUser();
userService.getUser("jack","root");
}

这样虽然使用的时候没有耦合了,但是BeanFactory里面还是有代码耦合的即:return UserService,那怎么办呢?可以利用反射创建对象

过渡时代进阶-反射

public class BeanFactory {
public static UserService getUser(){
UserService userService=null;
try {
Class<?> clazz = Class.forName("com.ty.service.UserServiceImpl");
userService= (UserService) clazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return userService;
}

这样比直接new好多了,减少了耦合,但是还有些不妥,获取类限定名的时候还是需要改来改去。即:

Class<?> clazz = Class.forName("com.ty.service.UserServiceImpl");

下面我们可以用properties属性配置文件存储文件限定名,代码如下:

userService=com.ty.service.UserServiceImpl

#这就实现把具体的类限定名和代码相分离,未来只需要修改此配置文件即可
public class BeanFactory {
private static UserService userService;
//创建Properties对象来加载properties属性配置文件
private static Properties environment = new Properties();
private static InputStream resource; static { //加载applicationContext.properties配置文件
resource = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
try {
environment.load(resource);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
resource.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} public static UserService getUserService() throws Exception { Class<?> clazz = Class.forName(environment.getProperty("userService"));
userService = (UserService) clazz.newInstance();
return userService;
}
}

这样未来增加了service代码,只需要修改properties配置文件即可,例如

public class BUserServiceImpl implements UserService {
private UserDao userDao= new UserDaoImpl();
@Override
public void getUser(String username, String password) {
System.out.println("B");
userDao.getUser(username,password);
}
}
#配置文件就改成这样
userService=com.ty.service.BUserServiceImpl
//测试文件
@Test
public void test2() throws Exception {
UserService userService= BeanFactory.getUserService();
userService.getUser("jack","root");
}

我们顺便用这种方式把UserService调用UserDao进行改进

public static UserDao getUserDao() {
UserDao userDao=null;
Class<?> clazz = null;
try {
clazz = Class.forName(environment.getProperty("userDao"));
userDao = (UserDao) clazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} return userDao;
} public class UserServiceImpl implements UserService {
private UserDao userDao= BeanFactory.getUserDao();
@Override
public void getUser(String username, String password) {
userDao.getUser(username,password);
}
}
userDao=com.ty.dao.UserDaoImpl
    @Test
public void test2() throws Exception {
UserService userService= BeanFactory.getUserService();
userService.getUser("jack","root");
}

工厂方法基本设计完成了,但是还有点小问题,那就是每次都需要在BeanFactory工厂类写一个与其对应的对象创建工厂方法,好麻烦,而且这些方法长得基本差不多,能不能设计一个通用的工厂方法呢,那必须能啊,上代码

public class BeanFactory {
private static Properties environment = new Properties();
private static InputStream resource; static { //加载applicationContext.properties配置文件
resource = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
try {
environment.load(resource);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
resource.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
*
* @param key 配置文件对应的userService,userDao
* @return
*/
public static Object getBean(String key){
Object returnedObject=null;
try {
Class<?> clazz = Class.forName(environment.getProperty(key));
returnedObject=clazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return returnedObject;
}
}
userService=com.ty.service.UserServiceImpl

userDao=com.ty.dao.UserDaoImpl
public class UserServiceImpl implements UserService {
private UserDao userDao= (UserDao) BeanFactory.getBean("userDao");
@Override
public void getUser(String username, String password) {
userDao.getUser(username,password);
}
} @Test
public void test2() throws Exception {
UserService userService= (UserService) BeanFactory.getBean("userService");
userService.getUser("jack","root");
}
}

这样一个通用工厂就完成了,这种方式你还需要先自己提供工厂类和方法,我们如果用Spring的话,工厂类不用我们手动实现,Spring提供了工厂

3、近代-IOC方式

ioc容器创建对象,这种方式我们后面会详细讲解

public class UserServiceImpl implements UserService {
private UserDao userDao; public UserDao getUserDao() {
return userDao;
} public void setUserDao(UserDao userDao) {
this.userDao = userDao;
} @Override
public void getUser(String username, String password) {
userDao.getUser(username,password);
}
}
<?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="userService" class="com.ty.service.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean> <bean id="userDao" class="com.ty.dao.UserDaoImpl"></bean>
</beans>
 @Test
public void test3(){
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) context.getBean("userService");
userService.getUser("jack","root");
}

这样我们就把创建对象的方式的一个小Demo写完了,只就是Spring框架的核心之一:ioc,我们先简单介绍一下Spring

二、spring介绍

我们交流的时候都说Spring是指Spring Framework,因为其它的分支模块都直接说了,比如SpringBoot、SpringCloud等等

官网地址:https://spring.io/projects/spring-framework

压缩包下载地址:https://repo.spring.io/release/org/springframework/spring/

源码地址:https://github.com/spring-projects/spring-framework

英文官网可能看不懂,github上还有一个中文网址,只不过不是最新版本的,不过没太大影响

https://gitee.com/fl_982659186/spring-docs

Spring 是为了解决企业级应用开发的复杂性而创建的。在 Spring 之前,有一个重量级的工具叫做 EJB,使用 Spring 可以让 Java Bean 之间进行有效的解耦,而这个操作之前只有 EJB 才能完成,EJB 过于臃肿,使用很少。Spring 不仅仅局限于服务端的开发,在测试性和松耦合方面都有很好的表现。 官网有一个简短的Spring介绍,说明Spring产生的原因

Spring makes programming Java quicker, easier, and safer for everybody. Spring’s focus on speed, simplicity, and productivity has made it the world's most popular Java framework.

总结就是Spring能为我们快速、轻松和安全的进行Java编程
详细:https://spring.io/why-spring

官网上还有一个Spring的概述

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

中文翻译:https://gitee.com/fl_982659186/spring-docs/blob/master/pages/overview/overview.md

核心解释

spring是一个一站式开源框架。

spring是为了简化企业开发而生的,使得开发变得更加优雅和简洁。

spring是一个IOCAOP的容器框架。

​ IOC:控制反转

​ AOP:面向切面编程

​ 容器:包含并管理应用对象的生命周期,就好比用桶装水一样,spring就是桶,而对象就是水

三、Spring 特点

​ 1、Spring通过DI、AOP和消除样板式代码来简化企业级Java开发

​ 2、Spring框架之外还存在一个构建在核心框架之上的庞大生态圈,它将Spring扩展到不同的领域,如Web服 务、REST、移动开发以及NoSQL

​ 3、低侵入式设计,代码的污染极低

​ 4、独立于各种应用服务器,基于Spring框架的应用,可以真正实现Write Once,Run Anywhere的承诺

​ 5、Spring的IoC容器降低了业务对象替换的复杂性,提高了组件之间的解耦

​ 6、Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式处理,从而提供了更好的复用

​ 7、Spring的ORM和DAO提供了与第三方持久层框架的的良好整合,并简化了底层的数据库访问

​ 8、Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可自由选用Spring框架的部分或全部

如何简化开发

​ 基于POJO的轻量级和最小侵入性编程

​ 通过依赖注入和面向接口实现松耦合

​ 基于切面和惯例进行声明式编程

​ 通过切面和模板减少样板式代码

四、Spring 框架结构

模块解释:
Test:Spring的单元测试模块
Core Container:核心容器模块,主要组件是 BeanFactory是不是好熟悉,上面咱们实现了一个简易版的BeanFactory
AOP+Aspects:面向切面编程模块
Instrumentation:提供了class instrumentation支持和类加载器的实现来在特定的应用服务器上使用,几乎不用
Messaging:包括一系列的用来映射消息到方法的注解,几乎不用
Data Access/Integration:数据的获取/整合模块,包括了JDBC,ORM,OXM,JMS和事务模块
Web:提供面向web整合特性

五、ioc初识

ioc(Inversion of Control ):控制反转,这是一个思想,简单一句话就是创建对象的控制权利交给Spring的容器 我们稍微详细展开一下

  • 谁控制谁
  • 控制什么
  • 什么是反转
  • 哪些方面被反转

先看一下官网如何介绍的

 IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern

 IOC与大家熟知的依赖注入同理,. 这是一个通过依赖注入对象的过程 也就是说,它们所使用的对象,是通过构造函数参数,工厂方法的参数或这是从工厂方法的构造函数或返回值的对象实例设置的属性,然后容器在创建bean时注入这些需要的依赖。 这个过程相对普通创建对象的过程是反向的(因此称之为IoC),bean本身通过直接构造类来控制依赖关系的实例化或位置,或提供诸如服务定位器模式之类的机制。

可能稍微晦涩,用现实的事物举个例子。我们要找女盆友,传统的方式是你自己按照标准亲自一步步筛选,然后就需要打听她们的兴趣爱好、qq号、电话号、微信号等等,想办法认识她们再继续下一步事情。控制反转的方式的话就是有一个婚介所,这个媒介所就是一个容器,里面有很多女生的资料,你把你的标准告诉工作人员,然后剩下的步骤由他们去操作,最后给你就返回一个符合你标准的女盆友,你就和她谈恋爱、结婚就行了。

说到这我们把上面演示过的demo画图演示一下

我们总结一下上面说的4个小问题

  • 谁控制谁:以前我们都是手动创建即new所需的对象,程序员自己来控制对象的创建过程。而有了IOC容器之后,就会变成由IOC容器来控制对象
  • 控制什么:实现过程中所需的对象以及所需依赖的对象
  • 什么是反转:以前我们自己new依赖对象就是正转,而有了反转之后,依赖的对象由ioc容器创建后注入到对象中,由主动创建变成了被动接受,这是反转
  • 哪些方面被反转:依赖的对象

DI

DI ( Dependency Injection ):依赖注入

很多人把IOC和DI说成一个东西,笼统来说的话是没有问题的,但是本质上还是有所区别的,希望大家能够严谨一点,IOC和DI是从不同的角度描述的同一件事,IOC是从容器的角度描述,而DI是从应用程序的角度来描述,也可以这样说,IOC是设计思想,而DI是具体的实现方式

上面的控制反转概念其实是模糊的 (可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系) ,所以后来就有了 “依赖注入” ,这个就很好理解,很直截了当就能说明IOC容器用来维护对象的依赖关系。

六、其它

我们面向对象设计的过程尽量达到低耦合,在面向对象设计的软件系统中,底层的实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑。

​ 需要注意的是,在这样的组合关系中,一旦某一个对象出现了问题,那么其他对象肯定回有所影响,这就是耦合性太高的缘故,但是对象的耦合关系是无法避免的,也是必要的。随着应用程序越来越庞大,对象的耦合关系可能越来越复杂,经常需要多重依赖关系,因此,无论是架构师还是程序员,在面临这样的场景的时候,都需要减少这些对象的耦合性。

​ 耦合的关系不仅仅是对象与对象之间,也会出现在软件系统的各个模块之间,是我们需要重点解决的问题。而为了解决对象之间的耦合度过高的问题,我们就可以通过IOC来实现对象之间的解耦,spring框架就是IOC理论最最广泛的应用。

从上图中可以看到,当引入了第三方的容器之后,几个对象之间就没有了耦合关系,全部对象都交由容器来控制,这个容器就相当于粘合剂,将系统的对象粘合在一起发挥作用。

Spring-步入Spring旅途的更多相关文章

  1. Spring 框架介绍 [Spring 优点][Spring 应用领域][体系结构][目录结构][基础 jar 包]

    您的"关注"和"点赞",是信任,是认可,是支持,是动力...... 如意见相佐,可留言. 本人必将竭尽全力试图做到准确和全面,终其一生进行修改补充更新. 目录 ...

  2. 深入分析Spring 与 Spring MVC容器

    1 Spring MVC WEB配置 Spring Framework本身没有Web功能,Spring MVC使用WebApplicationContext类扩展ApplicationContext, ...

  3. spring/spring boot/spring cloud开发总结

    背景        针对RPC远程调用,都在使用dubbo.dubbox等,我们也是如此.由于社区暂停维护.应对未来发展,我们准备尝试新技术(或许这时候也不算什么新技术了吧),选择使用了spring ...

  4. Spring 系列: Spring 框架简介 -7个部分

    Spring 系列: Spring 框架简介 Spring AOP 和 IOC 容器入门 在这由三部分组成的介绍 Spring 框架的系列文章的第一期中,将开始学习如何用 Spring 技术构建轻量级 ...

  5. Maven+Spring MVC Spring Mybatis配置

    环境: Eclipse Neon JDK1.8.0 Tomcat8.0 先决条件: Eclipse先用maven向导创建web工程.参见本站之前随笔. 本机安装完成mysql5:新建用户xuxy03设 ...

  6. [原创]java WEB学习笔记109:Spring学习---spring中事物管理

    博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好 ...

  7. 手动创建Spring项目 Spring framework

    之前学习框架一直是看的视频教程,并且在都配套有项目源码,跟着视频敲代码总是很简单,现在想深入了解,自己从官网下载文件手动搭建,就遇到了很多问题记载如下. 首先熟悉一下spring的官方网站:http: ...

  8. [Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.

    前言: 在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习 ...

  9. Spring MVC+Spring +Hibernate配置事务,但是事务不起作用

    最近做项目,被一个问题烦恼了很久.使用Spring MVC+Spring +Hibernate开发项目,在使用注解配置事务管理,刚开始发现无论如何数据库都无法更新,但是可以从数据库查询到数据.怀疑是配 ...

  10. 菜鸟学习Spring——初识Spring

    一.概念. Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Develop ...

随机推荐

  1. 用FL Studio制作反向人声音效(Vocal Chops)

    人声切片在各类电子音乐中都被广泛运用,在FL Studio20中我们也可以运用其自带的插件来制作属于我们自己的人声切片效果.在学完这篇文章后你就可以动手做出如Kygo.Martin Garrix等大牌 ...

  2. [BUGCASE]Phantom服务代码不健壮导致无法发送报表邮件

    一.问题描述 广告平台中的发报表邮件功能偶尔会出现发送失败的情况,重启phantom服务之后就好了 查看phantom服务的日志发现,在2017-12-12 03:29:45有访问记录,并且参数是异常 ...

  3. vue 项目在 IE11 里呈现空白,不兼容的问题解决方案

    我用vue 2.6.11版本编写的项目,在谷歌浏览器上运行的好好地,但是放到ie11浏览器上却是一片空白. 这个问题遇到的时候,我是蒙蔽了,抓紧去搜了搜百度,百度上的答案倒是都很统一. 都是说ie不兼 ...

  4. EF Core 执行SQL语句和存储过程

    无论ORM有多么强大,总会出现一些特殊的情况,它无法满足我们的要求.在这篇文章中,我们介绍几种执行SQL的方法. 表结构 在具体内容开始之前,我们先简单说明一下要使用的表结构. public clas ...

  5. PyQt(Python+Qt)学习随笔:Qt Designer组件属性编辑界面中对话窗QDialog的modal属性

    modal属性表示窗口执行show()操作时是以模态窗口还是非模态窗口形式展示,缺省为False,设置该值与QWidget.windowModality的值设置为 Qt.ApplicationModa ...

  6. 第15.13节 PyQt(Python+Qt)入门学习:Qt Designer的Spacers部件详解

    一. 引言 在Designer的部件栏中,有两种类型的Spacers部件,下图中上面布局中为一个水平间隔部件(按钮1和按钮2之间的部件),下面布局中为一个垂直间隔部件(按钮3和4之间),如图: 这两种 ...

  7. linux 的bash 和 反斜杠

    export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12 export GLUE_DIR=/path/to/glue python run_ ...

  8. 查询时间倒退一天-项目中惊现神秘BUG-JsonFormat使用采坑记

    一.问题由来 前一天下午正在写代码的时候,领导突然走过来跟我说,让我去看一个神秘的BUG,说是在数据库中查询时的一个日期 返回到页面后,查询时间倒退了一天.一听到这个BUG,我就感觉很奇怪,还有这样的 ...

  9. Python 反序列化漏洞学习笔记

    参考文章 一篇文章带你理解漏洞之 Python 反序列化漏洞 Python Pickle/CPickle 反序列化漏洞 Python反序列化安全问题 pickle反序列化初探 前言 上面看完,请忽略下 ...

  10. 树的直径,LCA复习笔记

    前言 复习笔记第6篇. 求直径的两种方法 树形DP: dfs(y); ans=max( ans,d[x]+d[y]+w[i] ); d[x]=max( d[x],d[y]+w[i] ); int di ...