Spring学习笔记

Posted 想成为大师啊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring学习笔记相关的知识,希望对你有一定的参考价值。

参考狂神说视频学习


1、Spring框架

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益 -----(摘自百度百科)

  • Spring:春天 —> 给软件行业带来了春天
  • 2002,首次推出了Spring框架的雏形:interface 21框架
  • Spring框架即以interface 21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日,发布1.0正式版
  • Rod Johnson,Spring Framework创始人,著名作者。
  • Spring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架。
  • SSH:Struct2 + Spring +Hibernate
  • SSM:SpringMVC + Spring + Mybatis

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

官方下载地址:http://repo.spring.io/release/org/springframework/spring

GitHub:https://github.com/spring-projects/spring-framework

maven - Spring Web MVC:

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.13</version>
</dependency>

优点:

  • Spring是一个开源的免费的框架(容器)
  • Spring是一个轻量级的、非入侵式的框架
  • 控制反转(IOC),面向切面编程(AOP)
  • 支持事务的处理,对框架整合的支持

总结:Spring就是一个轻量级的控制反转(IOC)和 面向切面编程(AOP)的框架

组成

  • 核心容器
    • 这是Spring框架最基础的部分,它提供了依赖注入(DependencyInjection)特征来实现容器对Bean的管理。这里最基本的概念是BeanFactory,它是任何Spring应用的核心。BeanFactory是工厂模式的一个实现,它使用IoC将应用配置和依赖说明从实际的应用代码中分离出来。
  • 应用上下文(Context)模块
    • 核心模块的BeanFactory使Spring成为一个容器,而上下文模块使它成为一个框架。这个模块扩展了BeanFactory的概念,增加了对国际化(I18N)消息、事件传播以及验证的支持。另外,这个模块提供了许多企业服务,例如电子邮件、JNDI访问、EJB集成、远程以及时序调度(scheduling)服务。也包括了对模版框架例如Velocity和FreeMarker集成的支持。
  • Spring的AOP模块
    • Spring在它的AOP模块中提供了对面向切面编程的丰富支持。这个模块是在Spring应用中实现切面编程的基础。为了确保Spring与其它AOP框架的互用性,Spring的AOP支持基于AOP联盟定义的API。AOP联盟是一个开源项目,它的目标是通过定义一组共同的接口和组件来促进AOP的使用以及不同的AOP实现之间的互用性。通过访问他们的站点,你可以找到关于AOP联盟的更多内容。
    • Spring的AOP模块也将元数据编程引入了Spring。使用Spring的元数据支持,你可以为你的源代码增加注释,指示Spring在何处以及如何应用切面函数。
  • JDBC抽象和DAO模块
    • 使用JDBC经常导致大量的重复代码,取得连接、创建语句、处理结果集,然后关闭连接。Spring的JDBC和DAO模块抽取了这些重复代码,因此你可以保持你的数据库访问代码干净简洁,并且可以防止因关闭数据库资源失败而引起的问题。
    • 这个模块还在几种数据库服务器给出的错误消息之上建立了一个有意义的异常层。使你不用再试图破译神秘的私有的SQL错误消息!另外,这个模块还使用了Spring的AOP模块为Spring应用中的对象提供了事务管理服务。
  • 对象/关系映射集成模块
    • 对那些更喜欢使用对象/关系映射工具而不是直接使用JDBC的人,Spring提供了ORM模块。Spring并不试图实现它自己的ORM解决方案,而是为几种流行的ORM框架提供了集成方案,包括Hibernate、JDO和iBATIS SQL映射。Spring的事务管理支持这些ORM框架中的每一个也包括JDBC。
  • Spring的Web模块
    • Web上下文模块建立于应用上下文模块之上,提供了一个适合于Web应用的上下文。另外,这个模块还提供了一些面向服务支持。例如:实现文件上传的multipart请求,它也提供了Spring和其它Web框架的集成,比如Struts、WebWork。
  • Spring的MVC框架
    • Spring为构建Web应用提供了一个功能全面的MVC框架。虽然Spring可以很容易地与其它MVC框架集成,例如Struts,但Spring的MVC框架使用IoC对控制逻辑和业务对象提供了完全的分离。
    • 它也允许你声明性地将请求参数绑定到你的业务对象中,此外,Spring的MVC框架还可以利用Spring的任何其它服务,例如国际化信息与验证。Spring框架Web页面乱码问题
    • 在做java Web项目时,乱码问题时常都会出现,解决方法也不尽相同,有简单也有复杂的;如果加入了Spring框架之后就不一样了,可以采用Spring框架自带的过滤器CharacterEncodingFilter,这样可以大大减轻了我们的工作量,即简单方便又容易理解

拓展:现代化的Java开发,说白就是基于Spring的开发

  • SpringBoot
    • 一个快速开发的脚手架
    • 基于SpringBoot可以快速的开发单个微服务
    • 约定大于配置
  • SpringCloud
    • SpringCloud是基于SpringBoot实现的

现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMVC,承上启下的作用

弊端:发展太久之后,违背了原来的理念。配置十分繁琐,人称 - 配置地狱


2、IOC理论推导

控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了

IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从IoC容器中取出需要的对象

在我们平时的业务逻辑中,通常使用MVC三层架构的形式;用test下面的类充当controller层

UserServiceImpl

package com.blb.service;

import com.blb.dao.UserDao;
import com.blb.dao.UserDaoImpl;

public class UserServiceImpl implements UserService 

    private UserDao userDao = new UserDaoImpl();

    public void getUser() 
        userDao.getUser();
    

MyTest

import com.blb.service.UserServiceImpl;

public class MyTest 
    public static void main(String[] args) 

        // 用户实际调用的是业务层, dao层他们不需要接触
        UserServiceImpl userServiceImpl = new UserServiceImpl();

        userServiceImpl.getUser();
    

那么我们要使用mysql,又要去service实现类里面修改对应的实现,假设我们的这种需求非常大,这种方式就根本不适用了,甚至反人类对吧,每次变动,都需要修改大量的代码。这种设计的耦合性太高了,牵一发而动全身

在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码!如果程序代码量十分大,修改一次的成本代价十分昂贵

所以利用set进行动态实现值的注入!,已经发生了革命性的变化

UserServiceImpl.java:

package com.blb.service;

import com.blb.dao.UserDao;
import com.blb.dao.UserDaoImpl;

public class UserServiceImpl implements UserService 

    private UserDao userDao;

    // 利用set进行动态实现值的注入!
    public void setUserDao(UserDao userDao) 
        this.userDao = userDao;
    

    public void getUser() 
        userDao.getUser();
    

MyTest.java

import com.blb.dao.UserDaoImpl;
import com.blb.dao.UserDaoMysqlImpl;
import com.blb.service.UserService;
import com.blb.service.UserServiceImpl;

public class MyTest 
    public static void main(String[] args) 

        // 用户实际调用的是业务层, dao层他们不需要接触
        UserService userService = new UserServiceImpl();

        // 接口不能使用实现类特有的方法, 需要强转
        ((UserServiceImpl) userService).setUserDao(new UserDaoImpl());

        userService.getUser();
    



两次的结果并不相同,而仅仅是在一个类中改变了new的对象(这里不需要在UserServiceImpl类中修改代码去实现不同需求,而是在Service层外的Servlet或叫Control层里,通过外部页面传递进来的请求参数来确定实现new哪个UserDao实现类)

好处:

  • 之前,程序是主动创建对象!控制权在程序猿手上
  • 使用了set注入后,程序不再具有主动性,而是变成了被动的接受对象
  • 这种思想,从本质上解决了问题,我们程序猿不用再去管理对象的创建了
  • 系统的耦合性大大降低,可以更加专注的在业务的实现上,这是IOC的原型

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)


3、Hello Spring

创建一个Hello.java

package com.blb.pojo;

public class Hello 

    private String str;

    public String getStr() 
        return str;
    

    public void setStr(String str) 
        this.str = str;
    

    @Override
    public String toString() 
        return "Hello" +
                "str='" + str + '\\'' +
                '';
    

然后在resources存放beans.xml,准备一个测试类(MyTest.java)

beans.xml

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 使用Spring来创建对象, 在Spring这些都称为Bean (id 随便写)

     类型变量名 = new 类型();
     Hello hello = new Hello();

     bean = 对象  new Hello();

     id = 变量名
     class = new的对象
     property 相当于给对象中属性设置一个值
     -->
    <bean id="hello" class="com.blb.pojo.Hello">
        <property name="str" value="Spring" />
    </bean>

</beans>

MyTest.java

import com.blb.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest 
    public static void main(String[] args) 

        // 获取Spring的上下文的对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        // 我们的对象现在都在Spring中的管理了, 我们要使用, 直接去里面取出来就可以了
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());
    


Hello对象是谁创建的?

  • Hello对象是由Spring创建的

Hello对象的属性是怎么设置的?

  • Hello对象的属性是由Spring容器设置的

这个过程就叫控制反转:

  • 控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的
  • 反转:程序本身不创建对象,而变成被动的接收对象
  • 依赖注入:就是利用set方法来进行注入的

IOC是一种编程思想,由主动的编程变成被动的接受,可以通过new ClassPathXmlApplicationContext去浏览一下底层源码

到现在,我们彻底不用再程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改,所谓的IoC:对象由Spring来创建,管理,装配!

可以换一种思想来理解:

  • 现在这套程序是:你告诉楼下餐厅,你要哪些菜,客人来的时候,餐厅把你需要的菜做好了送上来,就相当于你请人吃饭
  • 原来那套程序是:你写好菜单买好菜,客人来了自己把菜炒好招待
  • 此时的区别就是:如果我还需要做其他的菜,我不需要自己搞菜谱买材料再做好,而是告诉餐厅,我要什么菜,什么时候要,你做好送来

对于第一个程序而言,我们可以做一个改动:

beanx.xml

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="mysqlImpl" class="com.blb.dao.UserDaoMysqlImpl" />

    <bean id="UserServiceImpl" class="com.blb.service.UserServiceImpl">
        <!--
            ref: 引用Spring容器中创建好的对象
            value: 具体的值, 基本数据类型
         -->
        <property name="userDao" ref="mysqlImpl" />
    </bean>

</beans>

MyTest.java

import com.blb.dao.UserDaoMysqlImpl;
import com.blb.service.UserService;
import com.blb.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest 
    public static void main(String[] args) 

        // 用户实际调用的是业务层, dao层他们不需要接触
        UserService userService = new UserServiceImpl();
        // 接口不能使用实现类特有的方法, 需要强转
        ((UserServiceImpl) userService).setUserDao(new UserDaoMysqlImpl());
        userService.getUser();

        System.out.println("--------------------------");

        // 获取ApplicationContext: 拿到Spring的容器
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        // 容器在手, 天下我有; 需要什么, 就直接get什么
        UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");
        userService.getUser();
    


4、IOC创建方式

1、使用无参构造创建对象,默认

User:(无参构造是默认的,除非设置有参构造)

package com.blb.pojo;

public class User 

    private String name;

    public User()
        System.out.println("User的无参构造");
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public void show()
        System.out.println("name=" + name);
    

beans.xml

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.blb.pojo.User">
        <property name="name" value="你好" />
    </bean>

</beans>

MyTest.java

import com.blb.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest 

    public static void main(String[] args) 
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("user");
        user.show();
    


2、假设我们要使用有参构造创建对象

MyTest.java

import com.blb.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest 

    public static void main(String[] args) 
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("user");
        user.show();
    


  • 第一种方式:下标赋值
    <bean id="user" class="com.blb.pojo.User">
    <!--        <constructor-arg value="你好"/>-->
        <!-- 第一种方式: 下标赋值 -->
        <constructor-arg index="0" value="你好" />
    </bean>
    
  • 第二种方式:通过类型创建,但不建议使用
    <bean id="user" class="com.blb.pojo.User">
        <constructor-arg type="java.lang.String" value="你好" />
    </bean>
    
  • 第三种方式:直接通过参数名
    <bean id="user" class="com.blb.pojo.User">
        <constructor-arg name="name" value="你好" />
    </bean>
    

现在我再创建一个UserT类,里面也有私有属性和构造方法

package com.blb.pojo;

public class UserT 

    private String name;

    public UserT()
        System.out.println("UserT被创建了");
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public void show()
        System.out.println("name=" + name);
    

然后在xml中进行注册

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.blb.pojo.User">
        <constructor-arg name="name" value="你好" />
    </bean>

    <bean id="userT" class="com.blb.pojo.UserT">

    </bean>
</beans>

MyTest.java

import com.blb.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest 

    public static void main(String[] args) 
        // Spring容器: 类似婚介网站
        ApplicationContext context = new ClassPathXmlApplicationCo

以上是关于Spring学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

用大白话说Spring的IOC,DI

Spring Cloud学习笔记-007

Spring MVC官方文档学习笔记之DispatcherServlet

Spring Cloud学习笔记-012

Spring_day03

Spring5一篇文章带你理解Spring5中的静态代理模式