Spring学习笔记1

Spring学习笔记-day1

第一章Spring概述

1.1spring是什么

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

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

1.2spring的发展历程

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

1.3spring的优势

方便解耦,简化开发

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

AOP编程的支持

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

声明式事务的支持

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

方便程序的测试

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

方便集成各种优秀框架

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

降低JavaEE API的使用难度

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

spring源码时经典的学习范例

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

1.4spring的体系架构

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

第二章 Spring IOC

2.1模拟Spring IOC过程

解耦的思想:

第一步:通过读取配置文件来获取要创建的对象全限定名。

第二步:使用反射来创建对象,避免使用new关键字。

模拟业务场景中的三层架构

controller ——service——dao

首先使用new关键字来创建要依赖的对象:

dao层封装对资源的操作:

package com.jzt.dao;

public interface IHelloDao {

    public void sayHello();
}
package com.jzt.dao.impl;

import com.jzt.dao.IHelloDao;

public class HelloDaoImpl implements IHelloDao {
    public void sayHello() {
        System.out.println("hello spring init!");
    }
}

service层封装具体的业务,依赖dao层

package com.jzt.service;

public interface IHelloService {

    public void sayHello();

}
package com.jzt.service.impl;

import com.jzt.dao.IHelloDao;
import com.jzt.dao.impl.HelloDaoImpl;
import com.jzt.service.IHelloService;

public class HelloServiceImpl implements IHelloService {

	//依赖dao时,需要开发人员new具体的依赖类
    private IHelloDao helloDao = new HelloDaoImpl();

    public void sayHello() {
        helloDao.sayHello();
    }
}

利用test来模拟controller

package com.jzt.test;

import com.jzt.factory.HelloFactory;
import com.jzt.service.IHelloService;
import com.jzt.service.impl.HelloServiceImpl;

/**
 * 模拟spring IOC的流程
 */
public class HelloTest {

    public static void main(String[] args) {
        //一般情况下,开发人员需要使用一个对象资源时,都是通过手动new的方式来获取这个资源的使用
        IHelloService iHelloService = new HelloServiceImpl();
        iHelloService.sayHello();
    }
}

以上是我们开发人员在不使用spring框架时,需要自己手动创建依赖对象,然后调用依赖对象的方法进行操作。

下面我们模拟Spring IOC的过程:

1)创建配置bean的配置文件beans.properties:

helloService=com.jzt.service.impl.HelloServiceImpl
helloDao=com.jzt.dao.impl.HelloDaoImpl

2)使用工厂来创建需要依赖的bean对象:

package com.jzt.factory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class HelloFactory {

    private static Map<String, Object> beans;

    private static Properties props;

    static {
        try {
            //首先加载配置文件
            props = new Properties();
            InputStream in = HelloFactory.class.getClassLoader().getResourceAsStream("beans.properties");
            props.load(in);
            beans = new HashMap<String, Object>();
            //加载配置文件中配置的bean的相关信息,这里主要是类的全限定名
            Enumeration keys = props.keys();
            while(keys.hasMoreElements()){
                String key = keys.nextElement().toString();
                String beanPath = props.getProperty(key);
                //通过反射根据类的全路径名来获取对象的实例
                Object bean = Class.forName(beanPath).newInstance();
                //将获取到的对象实例放入容器中
                beans.put(key, bean);
            }
        } catch (Exception e) {
            System.out.println("初始化失败");
            e.printStackTrace();
        }
    }

    //提供一个公共的获取对象实例的方法
    public static Object getInstance(String beanName){
        return beans.get(beanName);
    }

}

3)在使用时,通过调用工厂的getInstance()公共方法,来获取需要的bean

package com.jzt.test;

import com.jzt.factory.HelloFactory;
import com.jzt.service.IHelloService;
import com.jzt.service.impl.HelloServiceImpl;

/**
 * 模拟spring IOC的流程
 */
public class HelloTest {

    public static void main(String[] args) {
        //一般情况下,开发人员需要使用一个对象资源时,都是通过手动new的方式来获取这个资源的使用
//        IHelloService iHelloService = new HelloServiceImpl();
//        iHelloService.sayHello();

        //spring的ioc是通过工厂+反射的方式来将资源加载到spring容器中供开发人员使用
        //下面我们通过工厂的方式来获取对象资源
        IHelloService helloService = (IHelloService) HelloFactory.getInstance("helloService");
        helloService.sayHello();
    }
}

package com.jzt.service.impl;

import com.jzt.dao.IHelloDao;
import com.jzt.dao.impl.HelloDaoImpl;
import com.jzt.factory.HelloFactory;
import com.jzt.service.IHelloService;

public class HelloServiceImpl implements IHelloService {

//    private IHelloDao helloDao = new HelloDaoImpl();

    private IHelloDao helloDao = (IHelloDao) HelloFactory.getInstance("helloDao");

    public void sayHello() {
        helloDao.sayHello();
    }
}

这样子,我们就可以不用自己手动的创建bean,把创建bean对象的工作交给factory工厂来做。而这种思想就是spring的IOC思想。

2.2Spring IOC的概述

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

控制反转(Inversion of Control,IOC):把创建对象的权利交给框架,是框架的重要特征。

作用:

削减计算机程序的耦合。(消除我们代码中的依赖关系)

2.3使用Spring IOC解决程序间的耦合

2.3.1准备Spring IOC的简单实现

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

也可以通过maven导入依赖:

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
    </dependencies>

简单使用:

1)生成beans.xml文件

<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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="helloService" class="com.jzt.service.impl.HelloServiceImpl"/>

    <bean id="helloDao" class="com.jzt.dao.impl.HelloDaoImpl"/>

</beans>

2)使用spring容器来获取需要的对象

package com.jzt.test;

import com.jzt.dao.impl.HelloDaoImpl;
import com.jzt.factory.HelloFactory;
import com.jzt.service.IHelloService;
import com.jzt.service.impl.HelloServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**8
 * spring IOC
 */
public class HelloTest {

    public static <HelloDao> void main(String[] args) {
        //获取spring容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        IHelloService helloService = (IHelloService) ac.getBean("helloService");
        HelloDao helloDao = (HelloDao) ac.getBean("helloDao", HelloDaoImpl.class);
        System.out.println(helloService);
        System.out.println(helloDao);
    }
}

可以正常获取到bean对象了:

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

显然,通过spring框架能够很方便的获取到需要的依赖对象,省去了开发人员大量的创建new对象的过程。同时很大程度上解耦。

2.3.2ApplicationContext的三个常用实现类

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

  • ClasspathXmlApplicationContext:可以加载类路径下的配置文件,要求配置文件必须放在类路径下(classpath)。 开发中更常用!
  • FileSystemXmlApplicationContext:可以加载磁盘下任意路径下的配置文件(前提是要有文件操作权限)。
  • AnnotationConfigApplicationContext:用于读取注解创建容器。。。
//        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        ApplicationContext ac = new FileSystemXmlApplicationContext("C:\\Users\\sj\\Desktop\\beans.xml");

2.2.3核心容器的两个接口

  • ApplicationContext:它在构建核心容器时,创建对象采用的策略是立即加载的方式。也就是说,只要一读取完配置文件马上就创建配置文件中配置的对象。(饿汉式)
  • BeanFactory:他在构建核心容器时,创建对象采用的策略是延迟加载的方式。也就是说,什么时候获取对象,就什么时候才真正的创建对象。(懒汉式)

2.2.4创建bean对象的方式

创建bean的三种方式:

(1)使用默认构造方法创建

​ 在spring配置文件中使用标签,配以id和class属性之后,且没有其他属性和标签时,采用的就是默认构造方法创建bean对象。

 <!-- 第一种方式:使用默认构造方法
     在spring配置文件中使用<bean>标签,配以id和class属性之后,且没有其他属性和标签时,采用的就是默认构造方法创建bean对象。
     -->
    <bean id="helloService" class="com.jzt.service.impl.HelloServiceImpl"/>

**此时如果该类中没有默认无参构造方法时,则对象将无法创建。

public class HelloServiceImpl implements IHelloService {
    private String name;
	//这里没有显式地创建默认构造方法,使用有参构造
    public HelloServiceImpl(String name) {
        this.name = name;
    }

    public void sayHello() {

    }
}

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

(2)使用普通工厂中的方法创建bean对象(或者是使用某个类中的方法来创建对象,并存入spring容器中)

首先创建工厂类,以及生成bean的方法:

package com.jzt.factory;

import com.jzt.service.impl.HelloServiceImpl;

/**
 * 模拟一个工厂,该类可能在jar保重,我们无法修改源码来创建默认构造方法
 */
public class InstanceFactory {

    public HelloServiceImpl getInstance(){
        return new HelloServiceImpl();
    }
}

配置bean:

<!-- 第二种种方式:使用普通工厂中的方法创建bean对象(或者是使用某个类中的方法来创建对象,并存入spring容器中)
    -->
    <bean id="instanceFactory" class="com.jzt.factory.InstanceFactory"/>
    <bean id="helloService" factory-bean="instanceFactory" factory-method="getInstance"/>

(3)使用静态工厂中的静态方法来创建bean对象(或者是使用某个类中的静态方法来创建对象,并存入spring容器中)

package com.jzt.factory;

import com.jzt.service.impl.HelloServiceImpl;

/**
 * 模拟一个工厂,该类可能在jar保重,我们无法修改源码来创建默认构造方法
 */
public class InstanceFactory {

    //使用普通方法
//    public HelloServiceImpl getInstance(){
//        return new HelloServiceImpl();
//    }

    //使用静态方法
    public static HelloServiceImpl getInstance(){
        return new HelloServiceImpl();
    }
}

配置bean:

    <!-- 第三种方式:使用静态工厂中的静态方法来创建bean对象(或者是使用某个类中的静态方法来创建对象,并存入spring容器中)
         -->
    <bean id="instanceFactory" class="com.jzt.factory.InstanceFactory" factory-method="getInstance"/>

2.2.5bean的作用范围

通过标签中的scope属性来设置bean对象的作用范围:

<!--    通过<bean>标签中的scope属性来设置bean对象的作用范围-->
    <bean id="helloService" class="com.jzt.service.impl.HelloServiceImpl" scope="prototype"/>
  • singleton:单例,默认的;
  • prototype:多例;
  • request:作用于web应用的请求范围;
  • session:作用于web应用的会话范围;
  • global-session:作用于集群环境中的会话范围(全局会话范围),再不是集群化解下,他就是session。

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

2.2.6bean对象的生命周期

(1)单例对象

  • 出生:当容器创建时,对象出生;
  • 活着:只要容器在,对象就存活;
  • 销毁:容器销毁,对象消亡;

总结:单例对象的生命周期和容器相同;

(2)多例对象

  • 出生:当我们使用对象时,spring框架会为我们创建对象;
  • 活着:对象只要被使用,就一直活着;
  • 销毁:对象长时间不使用,没有其它对象引用时,由GC回收;

2.3spring的依赖注入

依赖注入:Dependency Injection

IOC的作用:降低程序间的耦合(依赖关系)

依赖关系的管理:以后都交给spring来管理;

​ 在当前类中需要其他类对象,由spring为我们提供,我们只需要在配置文件中说明;

依赖关系的维护:就称之为依赖注入;

依赖注入:

  • 能注入的数据:
    • 基本类型和String
    • 其他bean类型(在配置文件中或者注解中配置过的bean)
    • 复杂类型和/集合类型
  • 注入的三种方式:
    • 使用构造方法注入;
    • 使用set注入;
    • 使用注解提供;

2.3.1使用构造函数注入

构造函数注入:

使用的标签:constractor-arg;

标签出现的位置:标签的内部;

标签中的属性

	- type:用于指定要注入的数据的数据类型,该数据类型也是构造函数某个活着某些参数 的类型;
	- index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值,索引的位置从0开始;
	- name:用于指定给构造函数中指定名称的参数赋值;**(常用)**
	- value:用于提供基本类型和String类型的数据;
	- ref:用于指定其他的bean类型数据。它指的就是在spring的ioc核心容器中出现过的bean对象。

前三个用于指定给构造函数中哪个参数赋值=======

优点:

​ 在获取bean对象时,注入数据是必须操作,否则无法创建对象;

弊端:

​ 改变类bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。

给bean添加属性参数:

package com.jzt.service.impl;

import com.jzt.dao.IHelloDao;
import com.jzt.dao.impl.HelloDaoImpl;

import com.jzt.service.IHelloService;

import java.util.Date;

public class HelloServiceImpl implements IHelloService {
    private String name;
    private Integer age;
    private Date date;

    public HelloServiceImpl(String name, Integer age, Date date) {
        this.name = name;
        this.age = age;
        this.date = date;
    }

    @Override
    public String toString() {
        return "HelloServiceImpl{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", date=" + date +
                '}';
    }

    public void sayHello() {

    }

}

配置:

<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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 通过构造函数注入属性值 -->
    <bean id="helloService" class="com.jzt.service.impl.HelloServiceImpl">
        <constructor-arg name="name" value="zhangsan"></constructor-arg>
        <constructor-arg name="age" value="18"></constructor-arg>
        <constructor-arg name="date" ref="now"></constructor-arg>
    </bean>

    <bean id="now" class="java.util.Date"></bean>

</beans>

2.3.2使用set方法注入

set方法注入:

使用的标签:property

标签出现的位置:标签的内部;

标签中的属性

	- name:用于指定调用时set方法名称;
	- value:用于提供基本类型和String类型的数据;
	- ref:用于指定其他的bean类型数据。它指的就是在spring的ioc核心容器中出现过的bean对象。

优点:

​ 创建对象时没有明确的限制,可以使用默认构造函数;

弊端:

​ 如果某个成员必须有值,则获取对象是某个set方法没有执行。

配置:

<bean id="now" class="java.util.Date"></bean>
    
    <!--  通过set方法注入  -->
    <bean id="helloService2" class="com.jzt.service.impl.HelloServiceImpl">
        <property name="name" value="testname"></property>
        <property name="age" value="18"></property>
        <property name="date" ref="now"></property>
    </bean>

调用:

//获取spring容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        IHelloService helloService = (IHelloService) ac.getBean("helloService2");
        System.out.println(helloService);

2.3.3通过注解注入(暂时略过,后面补充)

2.3.4复杂类型注入

复杂类型的注入/集合类型的注入:

  • 用于给list(Array、List、Set)类型集合注入的标签:、、
  • 用于给map(Map、Props)类型集合注入的标签:

含有复杂类型的对象:

package com.jzt.service.impl;

import com.jzt.service.IHelloService;

import java.util.*;

public class HelloServiceImpl2 implements IHelloService {
    private String[] array;
    private List list;
    private Set set;
    private Map map;
    private Properties props;

    public String[] getArray() {
        return array;
    }

    public void setArray(String[] array) {
        this.array = array;
    }

    public List getList() {
        return list;
    }

    public void setList(List list) {
        this.list = list;
    }

    public Set getSet() {
        return set;
    }

    public void setSet(Set set) {
        this.set = set;
    }

    public Map getMap() {
        return map;
    }

    public void setMap(Map map) {
        this.map = map;
    }

    public Properties getProps() {
        return props;
    }

    public void setProps(Properties props) {
        this.props = props;
    }

    @Override
    public String toString() {
        return "HelloServiceImpl2{" +
                "array=" + Arrays.toString(array) +
                ", list=" + list +
                ", set=" + set +
                ", map=" + map +
                ", props=" + props +
                '}';
    }

    public void sayHello() {

    }

}

配置:

 <!--  复杂类型注入  -->
    <bean id="helloService3" class="com.jzt.service.impl.HelloServiceImpl2">
        <property name="array">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
        </property>
        <property name="list">
            <list>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </list>
        </property>
        <property name="set">
            <set>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </set>
        </property>
        <property name="map">
            <map>
                <entry key="t1" value="AAA"></entry>
                <entry key="t2" value="BBB"></entry>
                <entry key="t3" value="CCC"></entry>
            </map>
        </property>
        <property name="props">
            <props>
                <prop key="t1">AAA</prop>
                <prop key="t2">BBB</prop>
                <prop key="t3">CCC</prop>
            </props>
        </property>
    </bean>

测试:

 //获取spring容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        IHelloService helloService = (IHelloService) ac.getBean("helloService3");
        System.out.println(helloService);

结果:

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

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页