zoukankan      html  css  js  c++  java
  • 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();
        }
    }
    
  • 相关阅读:
    区块链基础语言(十二)——Go语言跳转语句
    区块链基础语言(十一)——Go语言循环语句
    区块链基础语言(十)——Go语言选择语句
    区块链基础语言(九)——Go语言运算符
    区块链技术语言(八)——Go语言常量
    区块链基础语言(七)——Go语言变量
    区块链基础语言(六)——Go语言数据类型
    区块链基础语言(五)——Go语言结构
    区块链基础语言(四)——Go语言工程管理
    人生苦短,我用 Python
  • 原文地址:https://www.cnblogs.com/stu-zhouqian/p/14221699.html
Copyright © 2011-2022 走看看