1、spring全家桶,由一堆框架构成,简称全家桶。

2、spring全家桶构成

起源书:J2EE Development without EJB

spring全家桶:

全家桶中比较常用的几个框架如下:==================================

springframework:框架的春天,通常说spring就是指的springframework

springboot:一键启动

springcloud:分布式开发

springframework构成如下图:

3、springframework核心概念

IOC:控制反转。

从自己new对象,变成IOC容器给你提供对象,IOC容器管理对象的创建和销毁。IOC容器创建的对象先拿在它自己手里,叫做bean。IOC容器就是springframework的core container,程序一启动,这个容器就会被创建。

那么这个容器怎么知道哪些对象需要由它创建和销毁呢?答案是通过注解或者XML配置指定。见第9条。

如果对象A通过注解告诉了IOC容器交给它创建,A中又依赖了其他对象B,IOC又如何帮我们创建呢,比如servlet中依赖了service,service中依赖了dao?答案是通过配置让IOC容器能自动识别,将B自动纳入容器管理创建和销毁。见第15条。

对象A交给IOC容器创建后,要使用A的时候怎么从IOC容器中获取呢?答案是:先通过接口拿到IOC容器,调用接口方法获取IOC容器中管理的对象。

DI:依赖注入。在容器中已经存在了一堆bean,容器会自动在容器中将有依赖关系的bean进行关系绑定。这个依赖关系需要我们在配置文件中指定。见第15条。

4、简单实现IOC:XML配置

需求分析:将BookServiceImpl和BookDaoImpl交给Spring管理,并从容器中获取对应的bean对象进行方法调用。

        1.创建Maven的java项目

        2.pom.xml添加Spring的依赖jar包,context依赖会自动导入IOC容器所需的四个依赖包,当然也可以自己挨个导入。。

        3 .创建BookService,BookServiceImpl,BookDao和BookDaoImpl四个类

        4.resources下添加spring配置文件,并完成bean的配置

        5.使用Spring提供的接口完成IOC容器的创建

        6.从容器中获取对象进行方法调用

 

<?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标签标示配置bean
           id属性标示给bean起名字
           class属性表示给bean定义类型
           //以下配置的意思就是将这两个类的对象交给IOC容器创建
       -->
    <bean id="bookDao" class="com.ldj.dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="com.ldj.service.impl.BookServiceImpl"/>
</beans>

5、简单实现DI

上面实现IOC的例子中,dao和service分别交给了IOC容器管理,IOC容器中存着这两个对象的bean,我们可以从IOC容器中取出dao和service对应的bean来使用,但是我们可以看到service中依然要我们自己new dao对象才行,那能否这里这个dao对象也由IOC容器给我们呢?spring提供了这样的功能。首先要将两个对象都交给IOC容器创建,然后在配置文件中绑定他们的关系,然后在service中一定要写一个set方法来,IOC容器会自动调用那个set方法来将它管理的dao对象给serveice。

<?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标签标示配置bean
    	id属性标示给bean起名字
    	class属性表示给bean定义类型
	-->
    <bean id="bookDao" name="bookDao2 bookDao3" class="com.ldj.dao.impl.BookDaoImpl"/>

    <bean id="bookService" name="bookService2" class="com.ldj.service.impl.BookServiceImpl" scope="prototype">
        <!--配置service与dao的关系-->
<!--        依赖注入!将DAO注入service中-->
        <!--property标签表示配置当前bean的属性
        		name属性表示配置哪一个具体的属性
        		ref属性表示参照哪一个bean
		-->
        <property name="bookDao" ref="bookDao"/>
    </bean>
</beans>

6、bean的别名,通过name属性配置,用处不大

7、控制获取到的bean是不是单例的,spring默认是单例的。通过scope配置非单例。在web项目中scope还可以控制对方存放在 哪个域对象中。

8、哪些适合单例,即适合交给spring管理?哪些不适合交给spring管理?

  • 为什么bean默认为单例?
    • bean为单例的意思是在Spring的IOC容器中只会有该类的一个对象
    • bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高
  • bean在容器中是单例的,会不会产生线程安全问题?
    • 如果对象是有状态对象,即该对象有成员变量可以用来存储数据的,
    • 因为所有请求线程共用一个bean对象,所以会存在线程安全问题。
    • 如果对象是无状态对象,即该对象没有成员变量没有进行数据存储的,
    • 因方法中的局部变量在方法调用完成后会被销毁,所以不会存在线程安全问题。
  • 哪些bean对象适合交给容器进行管理?
    • 表现层对象
    • 业务层对象
    • 数据层对象
    • 工具对象
  • 哪些bean对象不适合交给容器进行管理?
    • 封装实例的域对象,因为会引发线程安全问题,所以不适合。

9、bean的实例化方式四种:bean就是对象,bean的实例化=bean的创建。原理:反射。

方式一:通过无参数构造方法创建。有有参构造的话必须要有无参构造。

方式二:静态工厂实例化,属性factory-method。极少使用,因为spring就是个大工厂了,我们没必要创建自己的工厂。

方式三:实例工厂。

方式三变种:实现springwork提供的FactoryBean接口。将我们写的工厂也放到IOC容器中管理!与其他框架连接!

<?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-->
<!--    <bean id="bookDao" class="com.ldj.dao.impl.BookDaoImpl"/>-->


    <!--方式二:使用静态工厂实例化bean-->
<!--    <bean id="orderDao" class="com.ldj.factory.OrderDaoFactory" factory-method="getOrderDao"/>-->

    <!--方式三:使用实例工厂实例化bean-->
<!--    <bean id="userFactory" class="com.ldj.factory.UserDaoFactory"/>

    <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>-->

    <!--方式四:使用FactoryBean实例化bean-->
    <bean id="userDao" class="com.ldj.factory.UserDaoFactoryBean"/>

</beans>

//FactoryBean创建对象

public class UserDaoFactoryBean implements FactoryBean {

//代替原始实例工厂中创建对象的方法

public UserDao getObject() throws Exception {//产出的对象

return new UserDaoImpl();

}

public Class getObjectType() {//产出对象的类型

return UserDao.class;

}

public boolean isSingleton() {//指定是否

return false;

}

}

10、spring报错,从下往上看

11、如何进行bean的初始化?

        init-method属性

12、如何才能执行bean的销毁?

        destory-method属性。

        暴力关容器ctx.close()。

        注册钩子关闭容器 ctx.registerShutDownHook()。

13、bean的生命周期

bean生命周期小结

(1)关于Spring中对bean生命周期控制提供了两种方式:

  • 在配置文件中的bean标签中添加init-method和destroy-method属性
  • 类实现InitializingBean与DisposableBean接口,这种方式了解下即可。

(2)对于bean的生命周期控制在bean的整个生命周期中所处的位置如下:

  • 初始化容器
    • 1.创建对象(内存分配)
    • 2.执行构造方法
    • 3.执行属性注入(set操作)
    • ==4.执行bean初始化方法==
  • 使用bean
    • 1.执行业务操作
  • 关闭/销毁容器
    • ==1.执行bean销毁方法==

(3)关闭容器的两种方式:

  • ConfigurableApplicationContext是ApplicationContext的子类
    • close()方法
    • registerShutdownHook()方法

14、spring允许有多个厂

15、DI依赖注入方式4种(简单数据类型、引用数据类型)

标准书写有以下两种,耦合较紧:

setter注入:类中写setter,配置文件bean标签中使用property标签。属性ref和value,一个使用引用数据类型,一个基本数据类型。

构造器注入:类中写带参构造器,配置文件bean标签中使用constructor-arg标签。属性ref和value,同上。

上面已经完成了构造函数注入的基本使用,但是会存在一些问题:

     当构造函数中方法的参数名发生变化后,配置文件中的name属性也需要跟着变这两块存在紧耦合,具体该如何解决?在解决这个问题之前,需要提前说明的是,这个参数名发生变化的情况并不多,所以上面的还是比较主流的配置方式。

标准写法构造器注入的另一种书写方式1,松耦合,但参数类型一样时无法解决:

不用name属性,用type属性区分给的参数位置

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> 
<constructor-arg type="int" value="10"/> 
<constructor-arg type="java.lang.String" value="mysql"/> 
</bean>

标准写法构造器注入的另一种书写方式2,松耦合:

不用name属性,用index属性区分参数位置


<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"> 
 <constructor-arg index="1" value="100"/> 
 <constructor-arg index="0" value="mysql"/> 
 </bean>

16、DI依赖注入方式的选择

两种参数的注入方式,具体我们该如何选择呢?

  1. 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
    • 强制依赖指对象在创建的过程中必须要注入指定的参数
  1. 可选依赖使用setter注入进行,灵活性强
    • 可选依赖指对象在创建过程中注入的参数可有可无
  1. Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
  2. 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
  3. 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
  4. ==自己开发的模块推荐使用setter注入==

17、上述方式都需要我们自己在配置文件中配置哪些对象需要注入,还要在类中写好构造器或者setter。spring提供了简化上述配置文件书写的方法,但没简化类的书写,且只能用于引用类型的依赖注入,即自动装配注入:

(1)、注入唯一的bean,可以用属性autowire=byType。推荐使用。

(2)、不唯一的bean,可以用autowire=byName。耦合较大,少用。

<?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 class="com.ldj.dao.impl.BookDaoImpl"/>
    <!--autowire属性:开启自动装配,通常使用按类型装配-->
    <bean id="bookService" class="com.ldj.service.impl.BookServiceImpl" autowire="byType"/>

</beans>

18、自动装配优先级低于setter注入和构造器注入。

19、以上实现了基本数据类型和引用数据类型的注入,但集合的注入有特殊的注入方法,极少用。

<?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 id="bookDao" class="com.ldj.dao.impl.BookDaoImpl">
        <!--数组注入-->
        <property name="array">
            <array>
                <value>100</value>
                <value>200</value>
                <value>300</value>
            </array>
        </property>
        <!--list集合注入-->
        <property name="list">
            <list>
                <value>888</value>
                <value>555</value>
                <value>boxuegu</value>
                <value>chuanzhihui</value>
            </list>
        </property>
        <!--set集合注入-->
        <property name="set">
            <set>
                <value>itcast</value>
                <value>1</value>
                <value>boxuegu</value>
                <value>boxuegu</value>
            </set>
        </property>
        <!--map集合注入-->
        <property name="map">
            <map>
                <entry key="country" value="china"/>
                <entry key="province" value="henan"/>
                <entry key="city" value="kaifeng"/>
            </map>
        </property>
        <!--Properties注入-->
        <property name="properties">
            <props>
                <prop key="country">china</prop>
                <prop key="province">henan</prop>
                <prop key="city">kaifeng</prop>
            </props>
        </property>
    </bean>
</beans>

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐