SpringIOC

spring必知必会

1.问题的讨论

在讲解spring框架之前,我们先引入一个思考,目前我们实现一个功能的基本流程如下:

① 创建一个web项目

② 创建数据库

③ 使用jsp技术完成页面的创建

④ 使用Servlet+MVC+Mybatis完成功能开发。

但是在目前的流程中,代码的执行流程如下:


重复的代码需要我们在不同的功能中,重复编写,极大的影响了开发的效率,怎么办?

不同的功能重复的代码不再重复声明,只声明功能相关的代码即可。也就说重复的代码我们虽然不写了,但是JDK在执行的时候这部分重复的代码仍然是存在的,执行的是重复的+自己的。

① 不同的方法中出现了重复代码-->将重复代码封装为工具方法,然后在自己的方法中调用工具方法,同时声明自己的代码。

② 不同的类中出现了重复的代码--->封装工具类

③ 不同的项目出现了重复代码--->封装jar包

那么什么是jar包呢?

jar包的本质:其实就是代码的class文件的压缩包,jdk可以直接调用无需解压。

jar包的使用:将jar包资源放入到项目中后,需要add as library.

jar包的特点:在项目中引入其他已经完成的代码的同时,保证项目原有代码的结构层次。

2.框架的概念和使用

1.框架的概念

不同的项目会使用相同的代码进行开发。而这部分代码如果要进行封装不是一个类或者一个方法就能搞定的,需要封装出来很多的类文件,于是为了方便其他人使用,我们再次将这些代码封装为jar包,所以,框架其实就是不用的项目都会使用的代码的封装,软件的半成品。

2.框架的本质:

就是别人封装好的功能代码。

3.框架的具体表现形式:

一堆jar包:封装好了都要使用的代码。

4.框架的使用:

① 将jar包导入到自己的项目中

② 查阅API文档,调用jar包中的资源完成功能开发

③ 配置框架的配置文件(框架代码运行需要的常量数据)

数据和代码的解耦,使用者可以通过配置问价来自定义数据。

5.框架的学习:

就是使用别人的代码完成自己的功能开发。其实就是学习如何使用别人的代码。想当于javaSE阶段学习常用类。

3.Spring框架的介绍

概念:Spring是一个控制反转(IOC)和面向切面的(AOP)的轻量级框架.

使用范围:任何java程序.

作用:

①简化企业项目的开发的流程.提升开发效率

②便于代码的后期维护升级.

③将代码之间的耦合性降低.

内容:

SpringIOC的使用

SpringAOP的使用

SpringTX的使用

注意:

Spring是一个框架集,内部集成了很多的功能,可以根据需求 选择对应的子框架使用.

Spring框架的结构:


Test层:Spring提供测试功能.

Core Container层:Spring启动最基本条件。

  1. Beans: Spring 负责创建类对象并管理对象。

  2. core:核心类。

  3. context:上下文参数,获取外部资源或管理注解。

  4. SpEL:expression.jar(Expression Language)
    注:spring启动需要的4个jar包。

Aop:实现aop功能需要依赖

Aspects:切面Aop依赖的包

Data Access/Integartion:Spring封装数据访问层相关内容

  1. JDBC:Spring对JDBC封装后的代码

  2. ORM:封装了持久层框架的代码,比如:Hibernate。

  3. TranSactions:对应Spring-tx.jar声明事务时使用。

Web:需要Spring完成web相关功能时需要

比如:由tomcat加载Spring配置文件时需要由Spring-web包。tomcat是servlet容器。

Spring发明人:Rod Johnson

4.SpringIOC的介绍和学习

中文名称:控制反转 英文名:Inversion of control

在使用MVC的结构体系来完成后台功能代码的声明时,在一定程度上降低了代码的冗余,但是层与层之间的耦合性过高,造成代码升级维护特别麻烦,比如,某天业务层某个类文件需要替换为新的类文件,那么,控制层所有调用该业务类的代码需要全部修改为调用新的业务类.

IOC是什么呢?

  • IOC完成的事情原先由程序员主动通过new实例化的对象的事情转交给Spring负责。

  • 控制反转中控制指的是:控制类的对象

  • 控制反转中反转指得是:转交给spring负责。

  • IOC最大的作用:解耦。程序员不需要管理对象,解除了对象管理和程序员的耦合。实现了层与层之间对象的逻辑性的解耦。

5.SpringIOC的基本使用

1.作用:

IOC将耦合性非常高的对象进行解耦.

2.时机:

什么时候使用IOC对对象进行解耦是一个主观问题,应当根据代码的结构以及功能的需求进行分析,然后决定哪些对象之间需要使用IOC解耦.一般情况下,在MVC代码结构中,会将Servlet和Service之间解耦,Service和mapper之间解耦.

3.基本使用流程:

  • 导入IOC的jar包
  • 在src下声明并配置applicationcontext.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="us" class="com.bjsxt.service.impl.ServiceImpl"></bean>
</beans>
  • 在代码中创建ApplicationContext对象,并获取Spring容器中的对象,然后完成功能开发

6.SpringIOC创建对象的三种方式

在学习了SpringIOC的基本使用流程后,我们使用IOC解耦层与层之间的逻辑关系,但是我们发现,对象由以前我们自己根据需求在代码中直接new创建,变为从Spring容器中获取,也就说对象的创建由Spring容器来创建,我们直接获取使用即可.那么,如果我们需要一个带有指定的初始化数据的对象,如何让Spring容器对象帮我们创建呢?

在applicationContext.xml配置文件中,配置对象的创建方式以及初始化的方式.

1.通过构造器方式

  • 无参数构造器(创建一个没有初始化数据的对象)
  • 有参数构造器(创建一个带有初始化数据的对象)

applicationContext.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">
    <!--创建student的bean对象-->
    <!--构造器方式-->
    <!--
    无参构造器 
    特点:Spring容器默认使用无参构造方式创建对象
    使用:在配置文件中直接使用bean标签配置即可,无需过多声明
    -->
    <bean id="stu" class="com.pojo.Student"></bean>
    
    <!--有参数的构造器
    特点:Spring容器对根据配置调用的有参构造器创建一个带有初始化数据的对象
    使用:constructor-arg:使用bean的字标签来声明调用的构造器的形参的个数
    一个字标签表示一个参数
    属性:index:参数的下标
          type:参数的类型,全限定路径
          name:参数的形参名
          value:参数要给的值
    -->
    <bean id="stu2" class="com.pojo.Student">
        <constructor-arg index="0" type="java.lang.Integer" name="sid" value="1"></constructor-arg>
        <constructor-arg index="1" type="java.lang.String" name="sname" value="张三"></constructor-arg>
    </bean>
</beans>

Test代码示例:

public class testStu {
    public static void main(String[] args) {
        //创建容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationcontext.xml");
        //获取容器中的对象
        //无参构造器方式
        Student student = (Student) ac.getBean("stu");
        System.out.println("无参构造:"+student);
        
        //有参构造器
        Student student1= (Student) ac.getBean("stu2");
        System.out.println("有参构造:"+student1);
        
    }
}

2.通过属性注入(get/set)

先通过空构造器创建一个对象,然后再使用set方法进行初始化赋值.

applicationContext.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">
    <!--创建student的bean对象-->
    <!--
    属性注入方式
    特点:相当于创建一个空对象然后使用set方法赋值
    使用:
    property:在bean标签下使用子标签property,表示调用set方法给某个属性赋值
    属性:name:要赋值的属性名
          value:值
    -->
    <bean id="stu3" class="com.pojo.Student">
        <property name="sid" value="2"></property>
        <property name="sname" value="李四"></property>
    </bean>
</beans>

TestObject代码示例:

public class testStu {
    public static void main(String[] args) {
        //创建容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationcontext.xml");
        //获取容器中的对象
        //属性注入方式
        Student student = (Student) ac.getBean("stu3");
        System.out.println("属性注入方式"+student);
    }
}

3.通过工厂模式

问题:

我们在使用Java代码处理某个问题的时候,需要创建A对象,调用 A对象中的某个方法,但是A对象的创建依赖B对象,而B对象的 创建又依赖于C对象,C对象的创建又依赖于D对象.....,如下:

D d=new D();

C c=new C(d);

B b=new B(c);

A a=new A(b);

这样造成,代码的阅读性极差

解决:

将对象的创建过程进行封装,直接返回创建好的对象使用.

实现:

工厂设计模式

本质:就是封装对象的创建过程的一种代码的编程思想

静态工厂:生产对象的方法是静态方法

public class AFactory{
public static A newInstance(){
        D d=new D();
        C c=new C(d)
        B b=new B(c);
        A a=new A(b);
        return a;
	}
}

动态工厂:生产对象的方法是非静态方法

public class AFactory{
public A newInstance(){
        D d=new D();
        C c=new C(d)
        B b=new B(c);
        A a=new A(b);
        return a;
	}
}

SpringIOC使用工厂创建对象:

传统方案:

我们自己创建工厂,然后调用工厂生产对象的方法,获取生产的对象,然后使用生产的对象完成功能开发.

IOC方案:

Spring容器创建工厂,并自动调用其创建的工厂的生产对象的方法,生产的对象直接存储在Spring容器中,我们直接从Spring容器中获取对象,完成功能开发.

①动态工厂模式

②静态工厂模式

applicationContext.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">
    <!--创建student的bean对象-->
    <!--工厂设计模式-->
    <!--动态工厂-->
        <bean id="factory" class="com.pojo.StudentFactory"></bean>
        <!--生产Student对象-->
        <bean id="stu4" factory-bean="factory" factory-method="newIntance"></bean>
    <!--静态工厂-->
    <!--可以理解为静态方法直接用类名调用-->
        <bean id="stu5" class="com.pojo.StudentFactory2" factory-method="newIntance"></bean>
</beans>

TestObject代码示例:

public class testStu {
    
    public static void main(String[] args) {
        //创建容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationcontext.xml");
        //获取容器中的对象
        //工厂设计模式     
            //动态工厂
            Student student = (Student) ac.getBean("stu4");
            System.out.println("动态工厂:"+student);
            //静态工厂
            Student student1 = (Student) ac.getBean("stu5");
            System.out.println("静态工厂:"+student1);
    }
}

7.IOC的依赖注入DI

  • 依赖注入DI的介绍

问题:

在学习了使用IOC创建对象的三种方式后,可以根据需求在applicationContext.xml文件中配置对象的创建方式.但是目前不管是属性注入方式,还是构造器方式,创建对象的时候,赋值赋予的都是基本类型的数据.但是对象中还有引用类型的属性,比如A对象中有属性B,我希望从Spring容器中获取一个B属性有值的A对象,怎么办?

对象之间的依赖关系:

我们在设计类对象时,会在类中声明其他类类型的属性,来调用其他类的资源完成当前类的功能处理,比如A类中声明B属性,在A类中就可以直接调用B类的资源完成A类的功能开发,但是A对象被创建时,其B属性必须有值,否则空指针异常,我们将此种也就是A和B的关系称为对象之间的依赖关系(A依赖B).

当一个类(A)中需要依赖另一个类(B)对象时,把B赋值给A的过程就叫依赖注入。

依赖责任链:

对象之间项目依赖形成的一条链式依赖关系.

D d=new D();

C c=new C(d)

B b=new B(c);

A a=new A(b);

A<---B<----C<----D

解决:

让Spring容器根据对象之间的依赖关系,将依赖责任连上的所有的对象全部配置为Bean对象.并且根据依赖关系完成对象之间的组装.将组装好的对象返回给用户使用.

概念:

DI:依赖注入,就是Spring容器根据对象之间的依赖关系完成对象的创建以及组装的过程.

applicationContext.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">
<!--
DI依赖的使用流程
①将依赖责任链上的所有的对象都配置为bean
②根据依赖关系完成对象之间的组装配置
     通过构造器方式:
         i.必须在类中声明对应的构造器
         ii.在bean标签下使用constructor-arg子标签完成以来注入
               使用constructor-arg的属性ref,ref的值为要注入的bean的ID
     通过set方法方式
          i.必须在类中声明引用属性对应的set方法
          ii.在bean标签下使用property子标签完成以来注入
               在property子标签中使用ref属性,属性值为要被注入的bean的ID
-->
    <!--配置学生bean对象-->
    <bean id="stu" class="com.pojo.Student">
        <!--构造器方式-->
        <!--<constructor-arg index="0" name="teacher" type="com.bjsxt.pojo.Teacher" ref="tea" ></constructor-arg>-->
        <!--set方式-->
        <property name="teacher" ref="tea"></property>
        <property name="sname" value="张三"></property>
        <property name="sid" value="1"></property>
    </bean>
    <bean id="tea" class="com.pojo.Teacher">
        <property name="tid" value="2"></property>
        <property name="tname" value="刘老师"></property>
    </bean>
</beans>

TestObject代码示例:

public class TestIocDI {
    public static void main(String[] args) {
        //获取spring对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationcontext.xml");
        Student stu = (Student) ac.getBean("stu");
        System.out.println(stu);
        stu.testStu();
    }
}
posted @ 2021-01-02 10:43  AndreasZhou  阅读(86)  评论(0编辑  收藏  举报