spring

一、Spring概述 
        1.1 web项目开发中的耦合度问题

                在Servlet中需要调用service中的方法,则需要在Servlet类中通过new关键字创建Service的实例

public interface ProductService{
      public List<Product> listProducts();
  }
 public class ProductServiceImpl1 implements ProductService{
      public List<Product> listProducts(){
          //查询热销商品
      }
  }
  public class ProductServiceImpl2 implements ProductService{
      public List<Product> listProducts(){
          //查询好评商品
      }
  }
 public class ProductListServlet extends HttpServlet{
      
      //在servlet中使用new关键字创建ProductServiceImpl1对象,增加了servlet和service的耦合度
      private ProductService productService = new ProductServiceImpl1();
      
      protected void doGet(HttpServletRequest request,HttpServletResponse response){
          doPost(request,response);
      }
      protected void doPost(HttpServletRequest request,HttpServletResponse response){
          productService.listProducts();
      }
  }

         在service实现类中需要调用DAO中的方法,也需要在servcie实现类通过new关键字创建DAO实现类对象
         如果使用new关键字创建对象:
                   失去了面向接口编程的灵活性
                   代码的侵入性增强(增加了耦合度)、降低了代码的灵活性

1.2 面向接口编程

解决方案:在Servlet中定义Service接口的对象变量,不使用new关键字创建实现类对象,在servlet的实例化的时候,通过反射动态的给Service对象变量赋值。

如何实现:Spring可以做到!!!

1.3 Spring介绍

         Spring是一个`轻量级的控制反转和面向切面的容器`框架,用来解决企业项目开发的复杂度问题—解耦

        - 轻量级:体积小,对代码没有侵入性
        - 控制反转:IoC(Inverse of Control),把创建对象的工作交由Spring完成,Spring在创建对象的时候同时可以完成对象属性赋值(DI)
        - 面向切面:AOP(Aspect Oriented Programming)面向切面编程,可以在不改变原有业务逻辑的情况下实现对业务的增强
        - 容器:实例的容器,管理创建的对象

1.4 Spring架构

官网 https://spring.io/

 Spring架构图

 1.4.1 Core Container

         Spring容器组件,用于完成实例的创建和管理
                 - core
                 - beans   实例管理
                 - context 容器上下文

1.4.2 AOP、Aspects

        Spring AOP组件,实现面向切面编程
                 - aop
                 - aspects

1.4.3 web
         Spring web组件实际指的是SpringMVC框架,实现web项目的MVC控制
                 - web (Spring对web项目的支持)
                 - webmvc (SpringMVC组件)

1.4.4 Data Access

        Spring数据访问组件,也是一个基于JDBC封装的持久层框架(即使没有mybatis,Spring也可以完成持久化操作)

1.4.5 Test

        Spring的单元测试组件,提供了Spring环境下的单元测试支持

二、Spring IoC — 基于XML

        Spring IoC 容器组件,可以完成对象的创建、对象属性赋值、对象管理

2.1 Spring框架部署(IoC)

        - core
        - beans
        - aop
        - expression
        - context

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

2.1.3 创建Spring配置文件

        通过配置文件"告诉"Spring容器创建什么对象,给对象属性赋什么值

        在resources目录下创建名为`appicationContext.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
       http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--  对于一个xml文件如果作为框架的配置文件,需要遵守框架的配置规则  -->
        <!--  通常一个框架为了让开发者能够正确的配置,都会提供xml的规范文件(dtd\xsd)  -->
        
</beans>

2.2 SpringIoC使用
        使用 SpringIoC组件创建并管理对象

2.2.1 创建一个实体类

public class Student {

    private String stuNum;
    private String stuName;
    private String stuGender;
    private int stuAge;
    private Date enterenceTime; //入学日期

}

2.2.2 在Spring配置文件中配置实体类

<?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将实体类配置给Spring进行管理,id表示实体类的唯一表示-->
        <bean id="stu" class="com.qfedu.ioc.bean.Student">
                <property name="stuNum" value="10002"/>
                <property name="stuName" value="李斯"/>
                <property name="stuGender" value="女"/>
                <property name="stuAge" value="20"/>
        </bean>

</beans>

2.2.3 初始化Spring对象工厂,获取对象
        ClassPathXMLApplicationContext

//1.初始化Spring容器,加载Spring配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.通过Spring容器获取Student对象
Student student2 = (Student) context.getBean("stu");

2.3 IoC和DI
        - IoC (Inverse of Control) 控制反转,通过Spring对象工厂完成对象的创建
        - DI (Dependency Injection)依赖注入,在Spring完成对象创建的同时依赖Spring容器完成对象属性的赋值

2.3.1 IoC

        当我们需要通过Spring对象工厂创建某个类的对象时候,需要将这个交给Spring管理——通过bean标签配置

<!--通过bean将实体类配置给Spring进行管理,id表示实体类的唯一表示-->
<bean id="stu" class="com.qfedu.ioc.bean.Student"></bean>

<bean id="book" class="com.qfedu.ioc.bean.Book"></bean>

2.3.2 DI

        通过Spring容器给创建的对象属性赋值

<bean id="clazz" class="com.qfedu.ioc.bean.Clazz"></bean>

<!--通过bean将实体类配置给Spring进行管理,id表示实体类的唯一表示-->
<bean id="stu" class="com.qfedu.ioc.bean.Student" autowire="byName">
    <property name="stuNum" value="10001"/>
</bean>

2.4 DI依赖注入

2.4.1 依赖注入三种方式

         Spring容器加载配置文件之后,通过`反射`创建类的对象,并给属性赋值;

         Spring容器通过反射实现属性注入有三种方式:

                 set方法注入

                 构造器注入

                 接口注入(不常用)

2.4.2 set方法注入
        在bean标签中通过配置property标签给属性属性赋值,实际上就是通过反射调用set方法完成属性的注入

简单类型及字符串

        直接通过property标签的value属性赋值

<!--通过bean将实体类配置给Spring进行管理,id表示实体类的唯一表示-->
<bean id="stu" class="com.qfedu.ioc.bean.Student" autowire="byName">
    <!--    简单类型    -->
    <property name="stuNum" value="10001"/>
    <property name="stuAge" value="12"/>
    <!--    字符串类型-->
    <property name="weight" value="62.3"/>
</bean>

日期类型 
方式1:在property标签中通过ref引用Spring容器中的一个对

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

<bean id="stu" class="com.qfedu.ioc.bean.Student" >
    <!--    日期类型-->
    <property name="enterenceTime" ref="date"/>
</bean>

方式2:在property标签中添加子标签bean来指定对象

<bean id="stu" class="com.qfedu.ioc.bean.Student" >
    <!--    日期类型-->
    <property name="enterenceTime">
        <bean class="java.util.Date"/>
    </property>
</bean>

自定义类对象属性

方式1:

<bean id="cla" class="com.qfedu.ioc.bean.Clazz">
    <property name="classId" value="2010"/>
    <property name="className" value="Java2010"/>
</bean>

<bean id="stu" class="com.qfedu.ioc.bean.Student">
    <!--  自定义对象类型-->
    <property name="clazz" ref="cla"/>
</bean>

方式2

<bean id="stu" class="com.qfedu.ioc.bean.Student">
    <!--  自定义对象类型-->
    <property name="clazz">
        <bean class="com.qfedu.ioc.bean.Clazz">
            <property name="classId" value="2010"/>
            <property name="className" value="Java2010"/>
        </bean>
    </property>
</bean>

 集合类型

List

        List<String>  List中的元素是字符串或者简单类型的封装类

<property name="hobbies" value="旅游,电影"/>

<property name="hobbies" >
      <list>
          <value>旅游</value>
          <value>电影</value>
          <value>Java</value>
      </list>
  </property>

        List<Object> List中的元素是对象类型

<property name="hobbies" >
      <list>
          <bean class="com.qfedu.ioc.bean.Book"/>
          <bean class="com.qfedu.ioc.bean.Book"/>
          <bean class="com.qfedu.ioc.bean.Book"/>
          <bean class="com.qfedu.ioc.bean.Book"/>
      </list>
  </property>
<property name="hobbies" >
      <list>
          <ref bean="book"></ref>  <!--引用容器中的bean-->
          <ref bean="book"></ref>
      </list>
  </property>

Set

<property name="sets">
      <set>
          <!--和list元素注入方式相同-->
          <bean class="com.qfedu.ioc.bean.Book"/>
          <bean class="com.qfedu.ioc.bean.Book"/>
          <bean class="com.qfedu.ioc.bean.Book"/>
          <bean class="com.qfedu.ioc.bean.Book"/>
      </set>
  </property>

Map

<property name="maps">
      <map>
          <entry>
              <key>
                  <value>k1</value>
              </key>
              <value>123</value>
          </entry>
          <entry>
              <key>
                  <value>k2</value>
              </key>
              <value>456</value>
          </entry>
      </map>
  </property>

Properties

<property name="properties">
      <props>
          <prop key="k1">aaa</prop>
          <prop key="k2">bbb</prop>
      </props>
  </property>

2.4.3 构造器注入

简单类型、字符串、对象

public class Student {

    private String stuNum;
    private String stuName;
    private String stuGender;
    private int stuAge;
    private double weight;
    private Date enterenceTime; //入学日期
    private Clazz clazz;

    public Student(String stuNum, String stuName, String stuGender, int stuAge, double weight, Date enterenceTime, Clazz clazz) {
        this.stuNum = stuNum;
        this.stuName = stuName;
        this.stuGender = stuGender;
        this.stuAge = stuAge;
        this.weight = weight;
        this.enterenceTime = enterenceTime;
        this.clazz = clazz;
    }
}
<bean id="date" class="java.util.Date"></bean>

<bean id="stu" class="com.qfedu.ioc.bean.Student">
    <constructor-arg index="0" value="10001"/>       <!--字符串类型-->
    <constructor-arg index="2" value="女"/>
    <constructor-arg index="1" value="张三"/>
    <constructor-arg index="3" value="21"/>       <!--简单类型-->
    <constructor-arg index="4" value="62.5"/>
    <constructor-arg index="5" ref="date"/>       <!--对象类型-->
    <constructor-arg index="6">                  <!--对象类型-->
        <bean class="com.qfedu.ioc.bean.Clazz"></bean>
    </constructor-arg>
</bean>

集合类型属性

public class Student{
    private List<String> hobbies;
    private Set<String> sets;
    private Map<String,Object> maps;
    private Properties properties;

    public Student(List<String> hobbies, Set<String> sets, Map<String, Object> maps, Properties properties) {
        this.hobbies = hobbies;
        this.sets = sets;
        this.maps = maps;
        this.properties = properties;
    }
}
<bean id="stu1" class="com.qfedu.ioc.bean.Student">
    <constructor-arg index="0">
        <list>
            <value>11</value>
            <value>22</value>
            <value>33</value>
        </list>
    </constructor-arg>
    <constructor-arg index="1">
        <set>
            <value>aa</value>
            <value>bb</value>
            <value>cc</value>
        </set>
    </constructor-arg>
    <constructor-arg index="2">
        <map>
            <entry>
                <key><value>key1</value></key>
                <value>value1</value>
            </entry>
            <entry>
                <key><value>key2</value></key>
                <value>value2</value>
            </entry>
        </map>
    </constructor-arg>
    <constructor-arg index="3">
        <props>
            <prop key="k1">v1</prop>
            <prop key="k2">v2</prop>
        </props>
    </constructor-arg>
</bean>

2.5 Bean的作用域
        在bean标签可以通过scope属性指定对象的的作用域

        scope="singleton"  表示当前bean是单例模式(默认饿汉模式,Spring容器初始化阶段就会完成此对象的创建;当在bean标签中设置 lazy-init="true"变为懒汉模式)

        scope="prototype" 表示当前bean为非单例模式,每次通过Spring容器获取此bean的对象时都会创建一个新的对象

单例

<bean id="book" class="com.qfedu.ioc.bean.Book" scope="singleton" lazy-init="true"></bean>

多例

<bean id="book" class="com.qfedu.ioc.bean.Book" scope="prototype"></bean>

2.6 Bean的声明周期方法

         在bean标签中通过init-method属性指定当前bean的初始化方法,初始化方法在构造器执行之后执行,通过destroy-method属性指定当前bean的销毁方法,销毁方法在对象销毁之前执行

Bean类

 public class Book {
  
      private int bookId;
      private String bookName;
  
       //初始化方法:在创建当前类对象时调用的方法,进行一些资源准备工作
      public void init(){
          System.out.println("-------init");
      }
  
      //销毁方法:在Spring容器销毁对象时调用此方法,进行一些资源回收性的操作
      public void destory(){
          System.out.println("-------destory");
      }
  }

Spring配置文件

<bean id="book" class="com.qfedu.ioc.bean.Book" scope="prototype"init-method="init" destroy-method="destory" ></bean>

2.7 自动装配

        自动装配:Spring在实例化当前bean的时候从Spring容器中找到匹配的实例赋值给当前bean的属性

        自动装配策略有两种:

                byName  根据当前Bean的属性名在Spring容器中寻找匹配的对象 ,如果根据name找打了bean但是类型不匹配则抛出异常

                byType  根据当前Bean的属性类型在Spring容器中寻找匹配的对象,如果根据类型找到了多个bean也会抛出异常

byName

<bean id="clazz" class="com.qfedu.ioc.bean.Clazz"></bean>

<bean id="stu2" class="com.qfedu.ioc.bean.Student" autowire="byName"></bean>

byType

<bean id="clazz2" class="com.qfedu.ioc.bean.Clazz"></bean>

<bean id="stu2" class="com.qfedu.ioc.bean.Student" autowire="byType"></bean>

2.8 SpringIoC 工作原理

  三、Spring IoC — 基于注解

        SpringIoc的使用,需要我们通过XML将类声明给Spring容器进行管理,从而通过Spring工厂完成对象的创建及属性值的注入;

        Spring除了提供基于XML的配置方式,同时提供了基于注解的配置:直接在实体类中添加注解声明给Spring容器管理,以简化开发步骤。

3.1 Spring框架部署
3.1.1 创建Maven项目

3.2.2 添加SpringIoC依赖

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

3.2.3 创建Spring配置文件

        因为Spring容器初始化时,只会加载applicationContext.xml文件,那么我们在实体类中添加的注解就不会被Spring扫描,所以我们需要`在applicationContext.xml声明Spring的扫描范围`,以达到Spring初始化时扫描带有注解的实体类并完成初始化工作

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 声明使用注解配置 -->
    <context:annotation-config/>

    <!-- 声明Spring工厂注解的扫描范围 -->
    <context:component-scan base-package="com.qfedu.beans"/>

</beans>

3.2 IoC常用注解
3.2.1 @Component

        类注解,声明此类被Spring容器进行管理,相当于bean标签的作用

        @Component(value="stu") value属性用于指定当前bean的id,相当于bean标签的id属性;value属性也可以省略,如果省略当前类的id默认为类名首字母改小写 

        除了@Component之外 @Service、@Controller、@Repository这三个注解也可以将类声明给Spring管理,他们主要是语义上的区别

        @Controller 注解主要声明将控制器类配置给Spring管理,例如Servlet

        @Service 注解主要声明业务处理类配置Spring管理,Service接口的实现类

        @Repository 直接主要声明持久化类配置给Spring管理,DAO接口

        @Component 除了控制器、servcie和DAO之外的类一律使用此注解声明

3.2.2 @Scope

         类注解,用于声明当前类单例模式还是 非单例模式,相当于bean标签的scope属性

        @Scope("prototype") 表示声明当前类为非单例模式(默认单例模式)
3.2.3 @Lazy

        类注解,用于声明一个单例模式的Bean是否为懒汉模式

        @Lazy(true) 表示声明为懒汉模式,默认为饿汉模式

3.2.4 @PostConstruct

        方法注解,声明一个方法为当前类的初始化方法(在构造器之后执行),相当于bean标签的init-method属性

3.2.5 @PreDestroy

        方法注解,声明一个方法为当前类的销毁方法(在对象从容器中释放之前执行),相当于bean标签的destory-method属性

3.2.6 @Autowired

        属性注解、方法注解(set方法),声明当前属性自动装配,默认byType

        @Autowired(required = false)  通过requried属性设置当前自动装配是否为必须(默认必须——如果没有找到类型与属性类型匹配的bean则抛出异常)

        byType

        ref引用

@Autowired
  public void setClazz(@Qualifier("c2") Clazz clazz) {
      this.clazz = clazz;
  }

3.2.7 @Resource

        属性注解,也用于声明属性自动装配

        默认装配方式为byName,如果根据byName没有找到对应的bean,则继续根据byType寻找对应的bean,根据byType如果依然没有找到Bean或者找到不止一个类型匹配的bean,则抛出异常。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值