欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring5学习笔记

程序员文章站 2022-07-13 10:38:04
...

Spring5学习笔记2.0

第1章 引言

  1. 工厂模式

第2章、第一个Spring程序

1 软件版本

1.JDk1.8+
2.Manven3.5+
3.IDEA2020
4.SpringFramework5.14

2 环境搭建

  • spring的jar包
#利用Manven来管理jar包 设置pom文件
<!-- 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

3.Spring的核心API

  • AppLicationContext(工厂接口)

    1.作用:Spring提供ApplicationContext工厂,用于对象的创建
    2.好处:解耦合
    
    • AppLicationContext接口的两个实现类:

      1.为什么使用接口:屏蔽实现的差异
      2.非web环境:ClassPathXmlAppLicationContext
      3.web环境:XmlWebApplicationContext
      
    • 重量级资源

      1 ApplicationContext的工厂对象占用大量内存
      2 不会频繁的创建该对象:一个应用只创建一个工厂对象
      3 ApplicationContext工厂:是线程安全的
      
    • 源码:可以看出是个ApplicationContext接口

      public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
      		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
              }
      

    4.程序开发

1.创建类型
2.配置applicationContext.xml文件
[id:唯一] [class:全限定路径名]

3.通过工厂类来获取对象
//1.获取spring的工厂
ApplicationContext context = new ClassPathXmlApplicationContext("/appLicationContext.xml");
//2.通过工厂获取对象
Person person = context.getBean(“person”, Person.class);




### 5. 细节分析

- 名词解释:

Spring工厂创建的对象叫做bean或者叫作组件(componet)


- Spring工厂中的常用方法:

~~~markdown
1 context.getBeanDfinitionNames()//返回配置文件中所有bean标签的id值

2 context.getBeanNameForType(类名.class)//返回配置文件中所有指定类型的bean的id值

3 context.containsBeanDfinition("Stirng")//判断是否存在指定id的bean

4 context.containsBean("String")//判断是否存在指定id或者name(别名)的bean
  • 配置文件中需要注意的细节

    1. 只配置class属性时<bean class="String"/>

      a). Spring会为bean提供一个默认的id值

      b). 一般在bean只被调用一次时采用这种方式配置

    2. name属性

      • 作用:作为bean对象的别名<bean name="String"/>

      • 于id属性的区别:

        a) 一个bean只能有一个id属性,但是可以定义多个name属性

        b) xml的id命名只能以字母开头

6.Spring工厂的底层实现原理

图解:

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KYpO07Kk-1620127891248)(C:\Users\Hooker\Pictures\Spring截图\spring原理图.PNG)]

7 思考

问:所有的对象都需要交给Spring工厂来创建吗?

答:理论上是的,但是实体对象(entity)例外,它交由持久层创建,因为它牵涉到数据库

第三章、Spring5与日志框架整合

1.为什么要整合日志框架?

Spring整合日志框架后,在程序运行时就可以在控制台中输出Spring的重要信息!

2.好处:

便于了解Spring的运行过程,利于调试

3.Spring如何整合日志框架?

1.引入log4j的jar包		
		<!--日志jar包-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>

2 引入log4j.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} %5-p %c{1}:%L - %m%n

第四章、注入(injection)

1.什么是注入?

1.通过Spring工厂及配置文件,为所创建的对象的成员变量赋值的过程就叫作注入。

2.为什么需要注入?

​ 因为通过代码编码的方式进行赋值在耦合1

3.如何进行注入?【开发步骤】

1 创建类成员变量的get和set方法。

2 配置Spring的配置文件<property name="id"></property>

4. 注入的好处

解耦合(从配置文件修改属性的值,不需要重新编译)

5.Spring注入的原理

Spring通过解析配置文件,然后调用类中的set()方法来完成成员变量的赋值。

图解:

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0WChq2gg-1620127891250)(C:\Users\Hooker\Pictures\Spring截图\spring注入原理.PNG)]

第五章、set注入

1.不同类型的成员变量的set注入:

​ 图解:

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9LPIZUUi-1620127891252)(C:\Users\Hooker\Pictures\Spring截图\类型注入图.PNG)]

2.JDK内置类型的set注入

2.2 String+8种基本数据类型 的set注入

<!--value可以写在标签内也可以写在标签体之间-->
<property name="id">
   <value>10</value>
</property>

<property name="name" value="张三"></property>

2.3 数组 的set注入

 <!--数组-->
<property name="emails">
   <list>
      <value>[email protected]</value>
      <value>[email protected]</value>
  </list>
</property>

2.4 Set集合 的set注入

 <!--Set集合-->
<property name="tels">
    <set>
		 <value>1234567</value>
         <value>1342424</value>
    </set>
</property>

2.5 List集合的set注入

<!--List集合-->
<property name="emails">
   <list>
      <value>[email protected]</value>
      <value>[email protected]</value>
  </list>
</property>

2.6 Map集合的set注入

<!--Map集合-->
<property name="qqs">
            <map>
                <entry>
                    <key><value>大号</value></key>
                    <value>1234567</value>
                </entry>
                <entry>
                    <key><value>小号</value></key>
                    <value>3131324</value>
                </entry>
            </map>
  </property>

2.6 Properties类型的set注入(特殊的Map)

 <property name="p">
     <props>
         <prop key="这是key1">这是值1</prop>
         <prop key="这是key2">这是值2</prop>
     </props>
 </property>

3.用户自定义类型的set注入

3.1 第一种方式:

  • 为成员变量提供get(),set()方法

  • 在bean标签中嵌套一个bean

        <bean id="userService" class="com.it.basic.UserServiceImpl">
            <property name="userDao">
                <bean class="com.it.basic.UserDaoImpl"></bean>
            </property>
        </bean>
    

3.2 第二种方式:

  • 把嵌套的bean单独提取出来 避免了重复创建bean对象
<!--先创建一个bean-->
<bean id="userDao" class="com.it.basic.UserDaoImpl"/>

<!--通过ref标签引用外部bean-->
<bean id="userService" class="com.it.basic.UserServiceImpl">
    <property name="userDao">
        <ref bean="userDao"/>
    </property>
</bean>

3.3 Set注入的简化写法

  • 基于命名空间p的简化写法(p => property)
<bean id="person" class="com.it.basic.Person" p:id="001" p:name="tom"/>


<bean id="userDao" class="com.it.basic.UserDaoImpl"/>
<bean id="userService" class="com.it.basic.UserServiceImpl" p:userDao-ref="userDao"/>

第六章、构造注入

- 注入:通过Spring的xml文件为成员变量赋值

- Set注入:Spring调用set()方法,通过解析xml文件为成员变量赋值

- 构造注入:Spring调用构造方法,通过配置文件为成员变量赋值

1.构造注入的开发步骤:

  • 提供有参构造方法
public class Customer implements Serializable {
    private String name;
    private int age;

    //有参构造函数
    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }
]
  • 配置xml文件
 <bean id="customer" class="com.it.basic.constructor.Customer">
    <!--一个constructor代表一个参数-->
    <constructor-arg index="0" value="tom"/>
    <constructor-arg index="1" value="18"/>
 </bean>

2.构造方法重载

  • 参数个数相同
通过控制<constructor-arg>标签的数量来区分
  • 参数个数不相同
通过在标签引入type标签来区分:<constructor-arg type="">

3.注入总结

图解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3vU0eawT-1620127891254)(C:\Users\Hooker\Pictures\Spring截图\注入总结.PNG)]

第七章、反转控制与依赖注入

1.反转控制IOC(Inverse Of Control)

1.控制:对成员变量赋值的控制权
2.反转控制:把对成员变量赋值的控制权从代码中转移到Spring工厂和配置文件中完成
3.好处:解耦合
4.底层实现原理:工厂设计模式

图解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xh254yYl-1620127891256)(C:\Users\Hooker\Pictures\Spring截图\反转控制原理.PNG)]

2.依赖注入DI (Dependency Injection)

1.注入:通过Spring配置文件对成员变量进行赋值
2.依赖注入:当一个类需要另一个类时,就意味着依赖,一旦出现依赖,就可以把另一个类当作本类的成员变量,最终通过Spring配置文件赋值
3.好处:解耦合

举例:

//UserService类中需要将UserDao类作为自己的成员变量,因此二者为依赖关系
public class UserServiceImpl implements UserService{
    private UserDao userDao;
    }

第八章、Spring工厂创建复杂对象

1.什么是复杂对象?

复杂对象就是指不能直接通过new来创建的对象

图解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CUzOPw8O-1620127891257)(C:\Users\Hooker\Pictures\Spring截图\复杂对象和简单对象.PNG)]

2.Spring工厂创建复杂对象的3种方式

(1)FanctoryBean接口

  • 开发步骤

    • 实现FanctoryBean接口

    图解:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mRjMxKkO-1620127891258)(C:\Users\Hooker\Pictures\Spring截图\FanctoryBean接口.PNG)]

    代码:

    public class ConnectionFactoryBean implements FactoryBean<Connection> {
    
        //用于书写复杂对象的代码
        public Connection getObject() throws Exception {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","152316");
            return conn;
        }
    
        //用于返回所创建复杂对象的Class对象
        public Class<?> getObjectType() {
            return Connection.class;
        }
    
        //返回ture只创建一个这种类型的对象
        //返回false每次都创建新的复杂对象
        public boolean isSingleton() {
            return false;
        }
    }
    
    • Spring配置文件的配置
    #如果class中指定的类 是FactoryBean接口的实现类 那么通过id值获取的对象是该类创建的复杂对象 Connection
    <bean id="conn" class="com.it.factorybean.ConnectionFactoryBean"/>
    
  • 开发细节

    1. 如果想要获取FactoryBean对象 ,则需要在类名前加一个”&“ getBean("&conn")
    //获取的是Connection对象
    Connection connection = context.getBean("conn",Connection.class);
    //获取的是ConnectionFactoryBean对象
    ConnectionFactoryBean connectionFactoryBean  = context.getBean("&conn",ConnectionFactoryBean.class);
    
    1. 解决Mysql高版本连接创建时,需要定制SSL证书的问题

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ShmZkzia-1620127891259)(C:\Users\Hooker\AppData\Roaming\Typora\typora-user-images\image-20201023155625414.png)]

    //将URl改为
    url="jdbc:mysql://localhost:3306/test?useSSL=false","root","root"
    
    1. 把ConnnectionFactoryBean中依赖的字符串信息 改为Spring文件的注入
    <bean id="conn" class="com.it.factorybean.ConnectionFactoryBean">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="152316"/>
    </bean>
    
  • FactoryBean的实现原理(接口回调)

1.为什么Spring规定创建复杂对象需要实现FactoryBean接口 并且要将实现的代码写在getObject()方法中?

2.为什么context.get("bean")获得的是复杂对象Connection 而没有获得ConnectionFactoryBean对象?

Spring内部实现流程:
1.通过conn获取ConnectionFactoryBean对象 然后通过instanceof来判断该对象是否是FactoryBean接口的实现
2.如果是,则调用其中getObject()方法创建Connection
3.返回Connection

图解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7iqcR7dX-1620127891259)(C:\Users\Hooker\Pictures\Spring截图\FactoryBean接口实现原理.PNG)]

  • FactoryBean的总结

    Spring原生提供的一种创建复杂对象的方式,在之后整合其他框架时将大量使用
    

(2)实例工厂

  • 作用
1.避免Spring框架的侵入
2.整合遗留系统
  • 开发步骤
  <!--代表遗留下来的Connection-->
  <bean id="connectionFactory" class="com.it.factorybean.ConnectionFactory"/>
  <!--重新整合-->
  <bean id="conn" factory-bean="connectionFactory" factory-method="getConnection"/>

(3)静态工厂

  • 开发步骤

在该类中创建一个静态方法

public class StaticConnectionFactory {
    public static Connection getConnection(){
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","152316");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
}

配置Spring文件

<bean id="conn" class="com.it.factorybean.StaticConnectionFactory" factory-method="getConnection"/>
  • Spring创建对象的总结

图解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OQ2hyify-1620127891260)(C:\Users\Hooker\Pictures\Spring截图\Spring创建工厂总结.PNG)]

第九章、控制创建Spring工厂对象的次数

1.如何控制简单对象的创建次数

在bean标签中加入scope属性 控制对象的创建次数
<bean id="conn" scope="prototype或者singleton" class="XX"/>

singleton:只创建一次简单对象(如果没有为scope赋值 默认是singleton)
prototype:每一次都会创建新的对象

2.如何控制复杂对象的创建次数

用FactoryBean中的isSingleton()方法来控制

//返回ture只创建一个这种类型的对象
//返回false每次都创建新的复杂对象
   public boolean isSingleton() {
        return false;
   }

3.为什么要控制对象的创建次数?

避免对象的重复创建,节省内存空间
  • 什么样的对象只创建一次
能被公用 线程安全的
1. sqlSessionFactory
2. DAO
3. Service
  • 什么样的对象要创建多次
不能被公用 线程不安全的
1. Connection
2. sqlSession | Session
3. Struts2 Action

第十章、对象(bean)的生命周期

1.什么是对象的生命周期

指的是一个对象创建、存活、消亡的一个完整过程

2.Spring Bean生命周期的三个阶段

  • 创建

    • 当scope=”singleton“时

      Spring工厂创建的同时,创建对象
      <bean id="product" scope="singleton" class="com.it.life.Product" />
      
      如果要在获取对象时才创建需要加上一个lazy-init属性
      <bean id="product" scope="singleton" class="com.it.life.Product" lazy-init="true"/>
      
    • 当scope="prototype"时

      Spring工厂在获取对象的同时,创建对象
      <bean id="product" scope="prototype" class="com.it.life.Product"/>
      
      context.getBean()//获取对象
      
  • 初始化

    Spring工厂在创建完对象后,调用对象的初始化方法,完成初始化工作
    注: 
    1. 初始化方法由程序员提供 
    2. 由Spring工厂调用
    3. 资源的初始化:数据库、IO、网络...
    
    • 方法一、实现InitializingBean接口

      //2.Spring检测到实现了InitialiaingBean接口后调用这个方法 进行初始化工作
      @Override
      public void afterPropertiesSet() throws Exception {
             //1.程序员根据需求实现这个方法,供Spring调用
      }
      
    • 方法二、对象中提供一个普通方法+配置文件

      //定义一个普通方法
      public void myInit(){
      
      }
      
      <!--让Spring能识别出这是一个初始化方法-->
      <bean id="product" class="XXX" init-method="myInit"/>
      
    • 细节:

      1. 方法一的优先级高于方法二
      2. 先注入后初始化(DI -> init)
      
  • 销毁

    当对象调用close()方法后 Spring会销毁对象
    
    • 方法1:实现DisposableBean接口

      //2.Spring调用销毁方法,销毁创建的对象
      @Override
      public void destroy() throws Exception {
          //1.程序员定义销毁方法
      }
      
    • 方法2:自定义普通方法+Spring配置文件

      public void myDestory(){
          
      }
      
      <bean id="product" class="com.it.life.Product" destroy-method="myDestroy"/>
      
    • 细节

      销毁方法只适用于scope="singleton"的情况
      
  • 图解Bean的生命周期

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-77rqzQc1-1620127891261)(C:\Users\Hooker\Pictures\Spring截图\Bean的生命周期.PNG)]


  1. 耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合 ↩︎

相关标签: Spring5 spring