maven配置
老杜Spring文字教程 mg9b

一、Spring启示录

mvc框架层.png
1、OCP
OCP是软件七大开发原则中最基本的一个原则,开闭原则。对扩展开放,对修改关闭。

OCP原则是最核心,最基本的,其他六个原则是为了这个原则服务的。

OCP开闭原则的核心是只要在扩展系统功能的时候,没有修改以前写好的代码就符合OCP原则。当进行系统功能扩展的时候,如果动了之前稳定的程序,修改之前的程序,之前所有程序都需要进行重新测试,这是不想看到的,非常麻烦。

2、依赖倒置原则 DIP原则

依赖倒置原则(DIP原则).png
依赖倒置原则是面向抽象编程,不面向具体编程。

目的是降低程序耦合度,提高扩展力。

上不依赖下就是复合依赖倒置,当下一改动,上就受到牵连就是不符合。



用控制反转IOC解决未被OCP又违背DIP的设计

反转两件事情:
1)不在程序中采用硬编码方式来new对象(new对象不管了,new对象的权利交出去了)
2)不在程序中采用硬编码方式来维护对象之间的关系(对象之间关系的维护全,不管了,交出去了)

控制反转是一种新的设计模式


Spring框架:
Spring框架实现控制反转IOC思想,既可以new对象,又可以维护对象与对象之间关系。

Spring框架是一个实现IOC思想的容器。

控制反转实现方式有多种,比较重要的叫做:依赖注入DI
控制反转是思想,依赖注入是这种思想的具体实现

依赖注入DI包括两种常见方式:set注入、构造方法注入
依赖注入中,依赖是A对象和B对象关系,注入是一种手段,通过这种手段让A对象和B对象产生关系(A与B之间的关系,考注入的手段来维护)

二、Spring概述

Spring.png
SSM三大框架:
S:Spring
S:SpringMVC
M:MyBatis(操作数据库的)

Spring特点:
1、轻量:非侵入式
2、控制反转
3、面向切面
4、容器
5、框架

三、Spring入门程序

在resources里面创建xml文件,这是bean的配置,配置格式为:

<?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">
<!--    这就是Spring的配置文件-->
<!--    idea工具为我们提供这个文件的模板,一定要使用这个模板来创建-->
<!--    这个文件不一定叫做spring.xml,可以其他名字-->
<!--    放在resources根目录下,相当于放到了类的根目录下-->
<!--    配置bean,这样sprig才可以帮助我们管理这个对象-->
<!--
    bean标签的两个主要属性:
        id:是这个bean的身份证号,不能重复
        class:必须填写类的全路径
-->
    <bean id="userBean" class="spring6.bean.User"/>
    <bean id="userDaoBean" class="spring6.dao.userDaoImplForMysql"/>
</beans>

在java类中调用:

public class FirstSpringTest {
    @Test
    public void testFirstSpringCode(){
        //第一步,获取Spring容器对象
        //ApplicationContext 翻译为:应用上下文,意思就是spring容器
        //ApplicationContext是一个接口
        //ClassPathXmlApplicationContext 专门从类路径中加载spring配置文件的一个spring上下文对象
        //这行代码只要执行,就相当于启动了spring容器,解析spring.xml文件,并且实例化所有的bean对象,放到spring容器当中
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");

        // 第二步:根据bean的id从Spring容器中获取这个对象
        Object userBean = applicationContext.getBean("userBean");
        System.out.println(userBean);

        Object userDaoBean = applicationContext.getBean("userDaoBean");
        System.out.println(userDaoBean);
    }
}

底层是通过反射机制调用无参构造方法

类型转换:

Date nowTime = (Date)applicationContext.getBean("nowTime");
Date nowTime = applicationContext.getBean("nowTime", Date.class);

ApplicationContext接口的超级父接口是BeanFactory,Spring的底层IOC是XML解析+工厂模式+反射机制实现的

启用Log4j2日志框架
1、引入依赖

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.19.0</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-slf4j2-impl</artifactId>
  <version>2.19.0</version>
</dependency>

2、在类的根路径下提供log4j2.xml配置文件(文件名固定为:log4j2.xml,文件必须放到类根路径下。)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <loggers>
        <!--
            level指定日志级别,从低到高的优先级:
                ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
        -->
        <root level="DEBUG">
            <appender-ref ref="spring6log"/>
        </root>
    </loggers>
    <appenders>
        <!--输出日志信息到控制台-->
        <console name="spring6log" target="SYSTEM_OUT">
            <!--控制日志输出的格式-->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-3level %logger{1024} - %msg%n"/>
        </console>
    </appenders>
</configuration>

3、使用

//1、创建日志记录器对象
//只要是FirstSpringTest里面的代码执行记录日志的话就输出相关的日志信息
Logger logger = LoggerFactory.getLogger(FirstSpringTest.class);
//2、记录日志
logger.info("一条消息");
logger.debug("一条调试信息");
logger.error("一条错误信息");

四、Spring对IOC的实现

4.1 控制反转IOC

  • 控制反转,反转的是什么?

    将对象的创建权利交出去,交给第三方容器负责。
    将对象和对象之间关系的维护权交出去,交给第三方容器负责。
  • 控制反转这种思想如何实现呢?

    DI(Dependency Injection):依赖注入
    

4.2 依赖注入

Spring通过依赖注入的方式来完成Bean管理的。
Bean管理说的是:Bean对象的创建,以及Bean对象中属性的赋值(或者叫做Bean对象之间关系的维护)。

  • 依赖注入:

    依赖指的是对象和对象之间的关联关系。
    注入指的是一种数据传递行为,通过注入行为来让对象和对象产生关系。
  • 依赖注入常见的实现方式包括两种:

    第一种:set注入
    第二种:构造注入
    

4.2.1 set注入

userDao.java

public class UserDao {
    private static final Logger logger = LoggerFactory.getLogger(UserDao.class);
    public void insert(){
        System.out.println("数据库正在保存数据。。。");
        logger.info("数据库正在保存数据info。。。");

    }
}

UserService.java

public class UserService {
    private UserDao userDao;
    private vipDao vipdao;
    //set注入的话,必须提供一个set方法
    //Spring容器会调用这个方法,来给UserDao属性赋值
    //自己写一个set方法,不使用idea工具生成,不符合Javabean规范
    //这个方法是以set单词开头的
    public void setMysqlUserDao(UserDao xyz){
        this.userDao = xyz;
    }
    public void setVipdao(vipDao vipdao) {
        this.vipdao = vipdao;
    }
    // alt+insert idea自动生成set方法
//    public void setUserDao(UserDao userDao) {
//        this.userDao = userDao;
//    }
    public void saveUser(){
        System.out.println("保存用户信息到数据库");
        userDao.insert();
        vipdao.insert();
    }
}

spring.xml

<!--配置Dao-->
    <bean id="userDaoBean" class="spring6.dao.UserDao"/>
    <bean id="vipDaoBean" class="spring6.dao.vipDao"/>
<!--配置service-->
    <bean id="userServiceBean" class="spring6.service.UserService">
<!--       想让spring调用对应的set方法,需要配置spring标签-->
<!--        name属性指定的值是set方法的方法名,去掉set然后把剩下的单词的首字母变小写-->
<!--        ref翻译为引用,ref后面指定的是要注入的bean的id-->
        <property name="mysqlUserDao" ref="userDaoBean"/>
        <property name="vipdao" ref="vipDaoBean"/>
    </bean>

4.2.2 构造注入

userDao.java

public class UserDao {
    private static final Logger logger = LoggerFactory.getLogger(UserDao.class);
    public void insert(){
        System.out.println("数据库正在保存数据。。。");
        logger.info("数据库正在保存数据info。。。");

    }
}

CustomerService.java

public class CustomerService {
    private UserDao userDao;
    private vipDao vipdao;

    public CustomerService(UserDao userDao, vipDao vipdao) {
        this.userDao = userDao;
        this.vipdao = vipdao;
    }

    public void save(){
        userDao.insert();
        vipdao.insert();
    }
}

spring.xml

<bean id="userDaoBean" class="spring6.dao.UserDao"/>
    <bean id="vipDaoBean" class="spring6.dao.vipDao"/>
    <bean id="customerService" class="spring6.service.CustomerService">
<!--        构造注入-->
<!--        指定构造方法的第一个参数,下标是0-->
        <constructor-arg index="0" ref="userDaoBean"/>
<!--        构造方法第二个参数,下标是1-->
        <constructor-arg index="1" ref="vipDaoBean"/>
<!--        可以不用index而用name-->
<!--        可以不用index与name,这种方式是根据类型进行注入-->
    </bean>

4.3 set注入

4.3.1 注入外部Bean

<bean id="orderServiceBean" class="spring6.service.orderService">
        <!--使用ref属性来引入,这就是注入外部Bean-->
        <property name="orderDao" ref="orderDaoBean"/>
</bean>

4.3.2 注入内部Bean

<bean id="orderServiceBean2" class="spring6.service.orderService">
        <property name="orderDao">
            <!--在property标签中使用嵌套的bean标签,这就是内部Bean-->
            <bean class="spring6.dao.orderDao"></bean>
        </property>
</bean>

4.3.3 注入简单类型

● 基本数据类型
● 基本数据类型对应的包装类
● String或其他的CharSequence子类
● Number子类
● Date子类
● Enum子类
● URI
● URL
● Temporal子类
● Locale
● Class
● 另外还包括以上简单值类型对应的数组类型

<bean id="svt" class="spring6.bean.SimpleValueType">
        <property name="age" value="20"/>
        <property name="age2" value="30"/>
        <property name="username" value="zhangsang"/>
        <property name="seasion" value="spring"/>
        <property name="flag" value="false"/>
        <property name="flag2" value="true"/>
        <property name="c" value="男"/>
        <property name="c2" value="女"/>
        <property name="clazz" value="java.lang.String"/>
<!--        报错了,无法把1999-09-21字符串转化为java.util.Date-->
<!--        <property name="birth" value="1999-09-21"/>-->
<!--        如果要把Date当作简单类型使用value,这个日期字符串格式有要求-->
<!--        实际开发中一般不会把date当作简单类型,一般会采用ref给date类型属性赋值-->
        <property name="birth" value="Mon May 01 23:06:30 CST 2023"/>
</bean>

4.3.4 级联属性赋值

<bean id="studentBean" class="spring6.bean.Student">
        <property name="student" value="张三"/>
        <property name="clazz" ref="clazzBean"/>
    </bean>
    <bean id="clazzBean" class="spring6.bean.Clazz">
        <property name="name" value="高三一班"/>
</bean>

变为:(Clazz需要增加get方法)

<bean id="clazzBean" class="spring6.bean.Clazz"/>

    <bean id="studentBean" class="spring6.bean.Student">
        <property name="student" value="张三"/>
        <property name="clazz" ref="clazzBean"/>
<!--        级联属性赋值-->
        <property name="clazz.name" value="高三一班"/>
</bean>

4.3.5 注入数组

简单类型

<bean id="yuQian" class="spring6.bean.QuanDaYe">
<!--        这个数组中元素是简单类型-->
        <property name="aiHaos">
            <array>
                <value>抽烟</value>
                <value>喝酒</value>
            </array>
        </property>
</bean>

非简单类型

<bean id="wo1" class="spring6.bean.Woman">
        <property name="name" value="小花"/>
    </bean>
    <bean id="wo2" class="spring6.bean.Woman">
        <property name="name" value="小美"/>
</bean>

<bean id="yuQian" class="spring6.bean.QuanDaYe">
<!--        这个数组不是简单类型-->
        <property name="womens">
            <array>
                <ref bean="wo1"/>
                <ref bean="wo2"/>
            </array>
        </property>
</bean>

4.3.6 注入List & Set

<bean id="persionBean" class="spring6.bean.Person">
        <property name="names">
            <list>
                <value>张三</value>
                <value>李四</value>
                <value>张三</value>
            </list>
        </property>
        <property name="address">
            <set>
                <value>广东</value>
                <value>湖南</value>
                <value>广东</value>
            </set>
        </property>
</bean>

4.3.7 注入Map集合 & 注入Properties

private Map<Integer,String> phones;
//注入属性类,本质上是一个Map
private Properties properties;
<property name="phones">
            <map>
                <entry key="1" value="110"/>
                <entry key="2" value="120"/>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="driver">com.mysql.cj.jdbc.Driver</prop>
                <prop key="url">jdbc:mysql://localhost:3360/spring6</prop>
            </props>
</property>

4.3.8 注入null和空字符串

不给属性注入,默认为null

<bean id="catBean" class="spring6.bean.Cat">
<!--        <property name="name" value="Tom"></property>-->
        <property name="age" value="2"/>
</bean>

//手动注入
<property name="name">
     <null/>
</property>

注入空字符串

//方法1
<property name="name" value=""/>
//方法2
<property name="name">
      <value/>
</property>

4.3.9 特殊符号注入

1、用转义字符代替特殊符号
2、用<![CDATA[]]>

<bean id="mathBean" class="com.powernode.spring6.beans.Math">
        <property name="result">
            <!--只能使用value标签-->
            <value><![CDATA[2 < 3]]></value>
        </property>
</bean>

4.4 p命名空间注入

目的:简化配置(简化set方法)
添加:xmlns:p="http://www.springframework.org/schema/p"

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    在spring头部加 xmlns:p="http://www.springframework.org/schema/p"-->
    <bean id="dogBean" class="spring6.bean.Dog" p:name="小花" p:age="3" p:birth-ref="birthdate"/>
<!--    获取当前日期-->
    <bean id="birthdate" class="java.util.Date"/>
</beans>

4.5 c命名空间注入

目的:简化配置(简化构造方法注入)
添加:xmlns:c="http://www.springframework.org/schema/c"

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="peopleBean" class="spring6.bean.People" c:_0="zhangsang" c:_1="30" c:_2="true">
    </bean>
</beans>

4.6 util命名空间注入

目的:让配置复用
添加:
xmlns:util="http://www.springframework.org/schema/util"
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd”

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    <util:properties id="prop">
        <prop key="driver">com.mysql.jdbc.Driver</prop>
        <prop key="url">jdbc://mysql://localhost:3360/spring</prop>
        <prop key="username">root</prop>
        <prop key="password">123456</prop>
    </util:properties>
    <!--    数据源1-->
    <bean id="ds1" class="spring6.bean.MyDataSource">
        <property name="properties" ref="prop"/>
    </bean>
</beans>

4.7 基于XML自动装配

Spring可以完成自动装配,可以根据名字进行自动装配,也可以根据类型进行自动装配
根据名字:

<bean id="orderServer" class="spring6.service.orderService" autowire="byName" />
<!--    id也叫做bean的名称 set去掉,第一个字母小写-->
<bean id="orderDao" class="spring6.dao.orderDao"/>

根据类型:(某种类型的实例只能有一个)

<bean class="spring6.dao.vipDao"/>
    <bean class="spring6.dao.UserDao"/>
    <bean id="cs" class="spring6.service.CustomerService" autowire="byType"/>

五、Bean的作用域

六、GoF工厂模式

七、Bean实例化方式

八、Bean生命周期

九、Bean循环依赖问题

十、回顾反射机制

十一、手写Spring框架

十二、Spring IOC注解式开发

十三、JdbcTemplate

十四、GoF代理模式

十五、面向切面编程AOP

十六、Spring对事务的支持

十七、Spring6整合JUnit5

十八、Spring6集成MyBatista3.5

十九、Spring中的八大模块

最后编辑:2023年05月18日 ©著作权归作者所有