Spring

https://www.bilibili.com/video/BV185411477k?p=142&spm_id_from=pageDriver
源自这个视频,讲的想到好,受益匪浅

什么是Spring
1.spring是一个轻量级的javaEE的解决方案 整合众多的- 优秀的设计模式

  • 轻量级
  • 1.面对运行环境没有额外的要求
  • 2.开源 tomcat resion jetty
  • 3.收费 webloginc websphere
  • 4.2.代码移植性高
  • 5.不需要实现额外的接口

javaEE解决方案

在这里插入图片描述

整合了设计模式

  1. 1.工厂
  2. 2.代理
  3. 3.模板
  4. 4.c策略

3.设计模式

  1. 广义的概念
  2. 面向对象设计中,解决特定问题的经典代码
  3. 2.侠义概念
  4. GOF4人帮的23种设计模式 工厂,适配器,装饰器,门面,代理,模板…

4.工厂设计模式

4.1. 什么是工厂设计模式

  1. 概念:通过工厂类 创建对象
  2.   User user=  new User();
    
  3.             UserDAo userDao=new UserDaoImpl();
    
  4. 好处:解耦合
  5. 耦合:指定是代码间的强关联关系,一方的改变会影响到另一方
  6. 问题:不利于代码的维护
  7. 简单:把接口的实现类,硬编译在程序中
  8. UserService userService=new UserServiceImple();
    

4.2. 简单工厂的设计

package com.baizhiedu.basic;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class BeanFactory {

    private static Properties env = new Properties();


    static {
        try {
            //第一步 获取io的输入流
            InputStream inputStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");


            //第二部文件内容 封装到Properties集合中 key= userService value=com.baizhiedu.basic.UserServiceImpl

            env.load(inputStream);


            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static UserService getUserService() {
/**
 * 对象的创建方式
 *
 *   1.直接调用构造方法 创建对像  UserService userService=new UserServiceImpl();
 * 2.通过反射的形式 创建对象 创建对象 解耦合
 * Class clszz= Class.forName("com.baizhiedu.basic.UserServiceImpl");
 * UserService userService= clazz.newInstance;
 *  */


        UserService userService = null;

        try {
            Class clazz = Class.forName(env.getProperty("userService"));
            userService = (UserService) clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return userService;
        //return  new UserServiceImpl();
    }


    public static UserDao getUserDao() {


        UserDao userDao1 = null;
        try {
            Class clazz = Class.forName(env.getProperty("userDao"));
            userDao1 = (UserDao) clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }


        return userDao1;

    }


}

4.3. 通用工厂的设计

问题:简单工厂会存在大量的臃余
在这里插入图片描述

通用工厂的代码

//创建一切想要的对象
public  static Object getBean( String key){
    Object ret=null;
    try{
        Class<?> clazz = Class.forName(env.getProperty(key));
        ret=clazz.newInstance();
    }catch (Exception e){
        e.printStackTrace();
    }
    return  ret;
}

4.4通用工厂的使用方式

  1. 1.定义类型
  2. 2.通过配置文件的配置告知工厂(applicationContext.properties)
  3. key=value
  4. 3.通过工厂获得类的对象
  5.             Object ret=  BeanFactory.getBean("key");
    

5.总结

  1. Spring本质 :工厂 ApplicationContext (applicationContext.xml)
    

第二章.第一个Spring程序

1.软件版本

  1. jdk 1.8+
  2. maven3.5+
  3. idea2018+
  4. springFramwork 5.1.4
  5. 官方网站www.spring.io

2.环境搭建

  • spring的jar包
  1. 1.设置pom 依赖
  2. <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
    
  • . spring配置文件

  • 配置文件的放置位置:任意位置,没有硬性的要求
    
  • 配置文件的命名  :没有硬性的要求  建议:applicationContext.xml
    
  • 思考:日后使用spring框架时 ,需要进行配置文件的设置
    在这里插入图片描述

    3.Spring的核心的APi

    • applicationContext
    1. 作用:spring提供的ApplicationContext这个工厂,用于对象的创建
    2. 好处用于解耦合
    • ApplicationContext接口类型
    1. 接口:屏蔽实现的差异
    2. 非web环境:classPathXmlApplicationContext(main junit)
    3. web环境下:xmlWebApplicationContext

在这里插入图片描述

  1. 重量级资源
  2. ApplicationContext工厂的对象占用大量的内存
  3. 不会频繁的创建对象:一个应用只会创建一个工厂对象
  4. ApplicationContext工厂:一定是线程安全的(多线程并发访问)

4.程序开发

1.1. 创建类型
2. 2.配置文件的配置 applicationContext.xml
3. <bean id="person" class="com.baizhiedu.basic.Person"/>

4.3. 通过工厂类获得对象
4. ApplicationContext
5. ClassPathXmlApplicationContext
6.

 //获取Spring的工厂
         ClassPathXmlApplicationContext xpx = new ClassPathXmlApplicationContext("/applicationContext.xml");
//2.通过工厂类来 获得对象
    Person person =(Person) xpx.getBean("person");
    System.out.println(person);

5.细节分析

  • 名词解释
  1. spring工厂创建的对象,叫做bean或者组件(commponet)
  • spring工厂的相关的方法
 //获取Spring的工厂
        ClassPathXmlApplicationContext xpx = new ClassPathXmlApplicationContext("/applicationContext.xml");
 //2.通过工厂类来 获得对象 不需要强制类型的转换
        Person person = xpx.getBean("person", Person.class);
      System.out.println(person);
        //当前spring配置文件中只能有一个(bean Class 是person类型)
        Person person = xpx.getBean( Person.class);
         System.out.println(person);
         
        // 获取的是spring工厂配置文件的所有的bean标签的id值  person  person1
   String[] beanDefinitionNames = xpx.getBeanDefinitionNames();
         for (String beanDefinitionName : beanDefinitionNames) {
         System.out.println(beanDefinitionName);
         }
         
//根据类型获取Spring配置文件中对应的id值
          String[] beanNamesForType = xpx.getBeanNamesForType(Person.class);
         for (String s : beanNamesForType) {
         System.out.println(s);

         }
//用于判断是否存在指定的id值的bean
       if (xpx.containsBeanDefinition("person")){
           System.out.println("true"+true);

       }else{
           System.out.println("false"+false);
       }
       

//用于判断是否存在id值bean

     if(xpx.containsBean("persion")){
          System.out.println(true);
        }else{
          System.out.println(false);
      }

  1. 设置配置文件要注意的细节

    1. 只配置class属性
    2. <bean  class="com.baizhiedu.basic.Persion"/>
      
    3. a)上述这种配置 有没有id值 com.baizhiedu.basic.Persion#0
    4. b)应用场景:如果这个bean只需要使用一次,那么就可以省略id值
    5. 如果bean会使用多次,或者被其他bean应用则需要设置id值
      
    6.  2.name属性
      
    7. 作用:用于在spring的配置文件中为bean对象定义别名(小名)
      
    8. 相同:
    9. 1.ctx.getBean("id|name")--->object
      
    10. 2.<bean id=" "  class=" "
      
    11. 等效
    12.   <bean  name=""  class="'
      
    13. 区别:
    14. 1.别名可以定义多个,但是id属性只能有一个值
    15.  2. xml的id属性  命名要求:必须以字母开头,字母  数字  下划线  连字符  不能以特殊字符开头   /person
      
    16. name 属性的值,没有要求 /person
    17. name 属性会应用在特殊的场景下:/person(Spring+struts1)
    18. xml 发展到今天:id属性的限制,不存在 /Person
    19. 3.代码
 //用于判断是否存在指定的id值的bean 只能判断id 不能判断name
      /** if (xpx.containsBeanDefinition("person")){
           System.out.println("true"+true);

       }else{
           System.out.println("false"+false);
       }
       

//用于判断是否存在id值bean  既可以判断id 也可以判断name

    /** if(xpx.containsBean("persion")){
          System.out.println(true);
        }else{
          System.out.println(false);
      }
*/

6.Spring 工厂的底层实现原理(简约版)

  • spring 工厂是可以调用对象私有的构造方法创建对象
    在这里插入图片描述

  • 思考

  • 问题:是不是在开发过程中,所有的对象,都会交给spring 工厂的来创建

  • 回答:理论上是的,但是有特例:实体对象(entity) 是不会交给spring 创建 它是由持久层框架进行创建的.

    第三章 spring5.x与日志框架的整合

    1.spring与日志的框架进行整合,日志框架就可以在控制台中,输出spring框架运行过程中的一些重要的信息
    2.好处:便于了解spring框架的运行过程,利于程序的调试

  • spring如何整合日志框架

    1. spring 1.2.3早期是用 commons-loggng.jar
      
    2. spring5.x 默认整合的日志框架 logback log4j2
      
    3. . Spring 5.x整合log4j
    4. 1.引入log4j jar包
    5. 2.引入log4.properties配置文件
      
  • pom

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
  • log4j.properties
 # resources 文件夹根目录下
 ### 配置根
log4j.rootLogger  = debug,console
 ###日志输出到控制台显示
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd  HH:mm:ss} %-5p %c{1}:%L - %m%n

第四章 注入(injection)

 1.什么是注入
       1.通过Spring工厂以及配置文件,为所创建对象的成员变量赋值
  1. 1.1为什么需要注入

    “通过编码的方式,为成员变量进行赋值,存在耦合”在这里插入图片描述
    1.2 如何进行注入(开发步奏)

  • 配置spring的配置文件
  <bean id="person1" name="p,p1" class="com.baizhiedu.basic.Person">
        <property name="id">
            <value>10</value>
        </property>
    <property name="name">

        <value>小贱人</value>
    </property>

    </bean>  

1.3注入的好处

  1. 解耦合 
    

2.spring注入原理分析(简易版)

在这里插入图片描述

Set注入的详解

  1. 针对 于不同类型的成员变量,在标签,需要嵌套其他类型的标签
  <property>
             xxxx
  </property>

在这里插入图片描述
1.jdk内置类型
1.1 String+8种基本数据类型

  1.    <value>suns</value>
    

1.2数组

<list>

                <value>
                    suan@qq.com
                </value>
                <value>
                    ssdfsn@qq.com
                </value>

                <value>
                    ffffffsn@qq.com
                </value>

            </list>

1.3 Set集合

           <set>
                <value>18888</value>
                <value>888888</value>
                 <value>999</value>

            </set>

1.4 List集合

           <list>
              <value>上帝</value>
                <value>仙女</value>
                <value>仙女</value>
            </list>

1.5 map集合

 <map>
            <entry>
                <key><value>小件</value></key>
                <value>很好</value>
            </entry>
            <entry>
                <key><value>大件</value></key>
                <value>很坏</value>
            </entry>
        </map>

1.6 Properties

           <props>
                <prop key="key1"> value1</prop>
                <prop key="key2"> value2</prop>
                <prop key="key3"> value3</prop>
            </props>

1.7 复杂的jdk类型 Date

  1.  需要程序员自定义类型转换器,处理
    

2.用户自定义类型

  • 为成员变量提供set get 方法
  • 配置文件中进行注入(赋值)
 <bean id="userService" class="XXXX.UserServiceImpl">
    <property name="userDao">
        <bean class="XXXXX.USerDaoImple"/>
    </property>

    </bean>

2.2第二种方式

  • 第一种赋值方式存在问题
  1. 1.配置文件存在庸于
  2. 2.被注入的对象(UserDao),多次创建,浪费(jvm)内存资源
  • 为成员变量提供set,get方法
  • 配置文件中进行配置
<bean id="userDao" class="XXX.UserDaoImpl"/>

 <bean id="userService" class="XXXX.UserServiceImpl">
    <property name="userDao">
        <ref bean="userDao"/>
    </property>

    </bean>
    #Spring 4.x 废除了<ref  local=""/>基本等效于<ref bean=" ">
  1. Set注入的简化的写法
    3.1 基于属性简化
<property name="name">
<value>suns</value>
</property>
<property name="name" value="suns"/>
注意:通过 value属性 只能简化 8种基本数据类型+string 注入标签

//用户自定义类型
<property name="userDao">
<ref bean="userDao"/>
</property>

<property name="userDao" ref="userDao"/>

3.2 基于p命名
在这里插入图片描述

第六章 构造注入

  1. 注入:通过spring的配置文件,为成员变量赋值
  2. Set注入:Spring调用set方法,通过配置文件 为成员变量赋值
  3. 构造注入:Spring调用的构造方法 通过配置文件 为成员变量赋值

1.开发步奏

  • 提供有构造方法
package com.baizhiedu.basic.construter;

import java.io.Serializable;

public class Customer  implements Serializable {
private  String name;
private int age;


    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

  • Spring 配置文件
<bean id="customer" class="com.baizhiedu.basic.construter.Customer">
        <constructor-arg>
            <value>suns</value>

        </constructor-arg>
        <constructor-arg>
            <value>102</value>
        </constructor-arg>

    </bean>
  1. 方法的重载
    2.1 当参数的构造个数不同时
1.通过控制<constructor-age>标签的数量进行区分

2.2 构造参数相同时

1通过在标签引入 type属性 进行类型的区分<constructor type=''>

3.注入的总结

  1. 未来的实战中,应用set注入还是构造注入?
    答案:set注入更多
    1.构造注入麻烦
    2.Spring框架底层 大量应用了 set注入

在这里插入图片描述

第七章 反转控制 与依赖注入

  1. 反转控制( IOC Inverse of Control)
  1. 对成员变量的赋值
  2. 反转控制:把对于成员变量赋值的控制权,从代码中 反转(转移) 到Spring 工厂和配置文件中去完成.
    3.好处:解耦合
  3. 底层实现:工厂设计模式
    在这里插入图片描述
  1. 依赖注入(Dependency Injecttion Di)
  1. 注入:通过spring工厂以及配置文件,为对象(bean 组件)的成员变量赋值

依赖注入:当一个类需要另一个类时,就意味着依赖,一旦出现依赖,就可以把另一个类作为本类的成员变量,最终通过Spring配置问价进行注入(赋值)
在这里插入图片描述

第八章.Spring 创建复杂对象

在这里插入图片描述

1.什么事复杂对象

复杂对象:指的就是不能直接通过new 构造方法创建的对象
Connection
SqlSessionFactory

2.Spring工厂创建复杂对象的的3种方式

  • 开发步奏
    • 实现factoryBean接口
      在这里插入图片描述
      在这里插入图片描述

    • Spring 配置文件的配置

#如果Class中指定的类型 是 FactoryBean接口剖的实现类,那么通过id值得的是这个类所创建的复杂对象 Connection
在这里插入图片描述

<bean id="conn" class="com.baizhiedu.factorybean.ConnectionFactoryBean"/>
  • 细节
    如果就想获得FactoryBean类型的对象,ctx.getBean("&conn")
    获得是ConnectionFactoryBean对象
 /**
     * 测试FactoryBean工厂
     */
    @Test
    public void test13(){
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        ConnectionFactoryBean conn = (ConnectionFactoryBean) ctx.getBean("&conn");
        System.out.println("conn="+conn);
    }
  • isStringleton方法

    返回 true 只会创建一个复杂对象
    返回false 每次会创建新的对象
    问题:根据这个对象的特点,决定返回的是true(sqlSessionFactory)还是false(Connection)

  • mysql高版本的连接创建时,需要制定SSL证书,解决问题的方式
  1. Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/suns?useSSL=false","root","123456");
    或者
    url=“jdbc:mysql://localhost:3306/suns?useSSL=false”
  • 依赖注入的体会(Di)

把ConnectionFactoryBean中依赖的四个字符串信息,进行配置文件的注入
好处:解耦合
在这里插入代码片
在这里插入图片描述

<bean id="conn" class="com.baizhiedu.factorybean.ConnectionFactoryBean">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/suns?useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>

    </bean>
  • FactoryBean的实现的原理

接口回调
1.为什么Spring规定FactoryBean接口实现 并且 getObject()?
2.ctx.getBean(“conn”)获得是复杂对象Connection 而没有获得ConnectionFactoryBean(&)

Spring内部运行流程
1.通过conn获得ConnectionFactory类的对象,进而通过instanceof 判断出是FactoryBean接口的实现类
2.Spring 按照规定调用 getObject()–>Connection
3.返回Connection
在这里插入图片描述

  • FactoryBean总结

1.Spring 中用于创建复杂对象的一种方式,也是Spring原生提供的,后续讲解Spring整合其他框架时,大量使用FactoryBean

2.1 实例化工厂

  1. 避免spring框架的侵入
  2. 整合遗留系统

在这里插入图片描述

<bean id ="connFactory" class="com.baizhiedu.factorybean.ConnectionFactory"></bean>
    <bean id="conn" factory-bean="connFactory" factory-method="getConnection"/>

2.3 静态工厂

  • 开发步奏
    在这里插入图片描述
  <bean id="conn" class="com.baizhiedu.factorybean.StaticConnectionFactory" factory-method="getConnection"/>

第九章,控制Spring创建工厂对象的次数

  1. 如何控制简单对象的创建次数
<bean id="account" scope="singleton|prototype" class="xxxx.Account"/>
sigleton:只会创建一次简单对象的默认值
prototype:每一次都会创建新的对象
  1. 如何控制复杂对象的创建次数
FactoryBean(
isSingletion(){
return true  只会创建一次

return  false  ,每次都会创建新的
}
)

如果没有isSingleton方法  还是通过scope 属性来控制创建的次数
3. 为什么要控制创建的次数?
  1. 好处:节省不必要的内存的浪费
  • 什么 样的对象只创建一次?
  1. sqlsessionFactory
  2. Dao
  3. Service
  • 什么样的对象 每次都要创建新的?
  1. Connection
  2. Sqlsession |session
    Struts2 Action
    总结线程安全的只创建一次即可,线程不安全的 要 创建多次

第十章 对象的生命周期

  1. 什么是对象的生命周期

指的是一个对象创建,存活,消亡的一个完整的过程

  1. 为什么要学习对象的生命周期

由spring负责对象的创建,存活,销毁,了解生命周期,有利于我们使用Spring为我们创建的对象

  1. 生命周期的3个阶段
  • 创建阶段
  1. Spring 工厂何时创建对象
  • scope=“singleton”
  1. Spring 工厂创建的同时,对象的创建

注意:设置scope=singleton 这种情况下,也需要在获取对象的同时,创建对象
<bean lazy-init="true"/>

  • scope =“prototype”

Spring 工厂会在获取对象的同时,创建对象
ctx.getBean(" ")

  • 初始化阶段

Spring 在创建完对象后,调用对象的初始化方法,完成对应的初始化操作

  1. 初始化方法提供:程序员根据需求,提供初始化方法,最终完成初始化操作
    2.初始化的方法调用:Spring工厂进行调用
  • 实现initializingBean接口
//程序员根据需求 实现的方法,完成初始化
punlic void afterProperitesSet(){


}
  • 对象提供一个普通的方法
public void myInit(){

}
<bean id="product" class="xxxx.Product" init-method="myInit">
  • 细节
  1. 如果一个对象即实现InittializingBean同时又提供的 普通的初始化方法,顺序
    1.1 InitializingBean
    1.2 普通初始化方法
  1. 注入一定发生在初始化前面
  2. 什么叫初始化操作
  1. 资源的初始化“数据库 io 网络。。。
  • 销毁阶段

Spring 销毁对象之前,会调用对象的销毁方法,完成销毁操作

  1. Spring 什么时候销毁所创建的对象?
    ctx.close();
    2.销毁方法:程序员根据自己的需求,定义销毁方法,完成销毁操作
    调用:spring 工厂完成调用
  • DisposableBean
pubilc void destroy() throws Exception{

}
  • 定义一个普通的销毁方法
public void myDestroy() throws Exception{
}

< bean id="" class="" init-method="" destroy-method="myDestroy"/>
  • 细节分析
  1. 销毁方法操作只适合于scope=“singleton”
  2. 什么叫销毁操作
  1. 主要指的就是 资源的释放操作 io.close() conection.close();
    在这里插入图片描述

第十一章,配置文件参数化

1.把spring配置文件中需要修改的 字符串信息,转移到一个更小的额配置文件中

  1. Spring配置文件中存在需要经常修改的额字符串?
    存在 以数据库连接相关的参数 代表
    2.经常变化的字符串,在spring 的配置文件中,直接修改.
    不利于维护(修改)
    3.转移到一个小的配置文件(.properties)
    利于维护(修改)

配置文件参数化:有利于Spring配置文件的维护(修改)在这里插入图片描述

1.配置文件参数的开发步奏

  • 提供一个小的配置文件(.properties)
名字:随便
放置位置:随便
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/suns?useSSL=false&allowPublicKeyRetrieval=true
jdbc.username=root
jdbc.password=123456
  • Spring配置文件与小配置文件进行整合

<!--Spring配置文件与小配置文件的整合-->
    <context:property-placeholder location = "classpath:/db.properties"/>


  • 在Spring 配置文件中通过${key}获取小配置文件中对应的值
    在这里插入图片描述

十二章 自定义类型转换器

  1. 类型转换器

作用:Spring通用类型转换器把配置文件中的字符串类型的数据,转换成了对象中的成员变量对应的类型的数据,进而完成了注入
在这里插入图片描述

  1. 自定义类型的转换器
  1. 原因:当spring内部都没有提供特定类型转换器时,而程序员在应用的过程中还需要使用,那么就需要程序员自己定义类型的转换器
  • 类implements Converter 接口
public class MyDateConverter implements Converter<String,Date> {

    /**
     * convert方法作用:String----->Date
     * SimpleDateFormat sdf=new SimpleDateFormat();
     * sdf.parset(String)---->Date
     * param:source 代表的是配置文件中  日期字符串<value>1999-08-18</value>
     * return :当把转换好的Date作为convert方法的返回值后,Spring自动的为birthday属性进行注入赋值
     * @param source
     * @return
     */
    @Override
    public Date convert(String source) {
        Date date=null;
        try{
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         date = dateFormat.parse(source);
        } catch (Exception e){
            e.printStackTrace();
        }

        return date;
    }
}
  • 在spring 的配置文件中进行配置
  1. MyDateConverter对象创建出来
   `<bean id="myDateConverter" class="xxx.myDateConverter"/>`
  1. 类的转换器的注册
目的:告知Spring框架,我们所创建的MyDateConverter是一个类型转换器
<!--Spring创建MyDateConverter类型转换器-->
    <bean id="myDateConverter" class="com.baizhiedu.converter.MyDateConverter"/>

    <!--用于注册类型转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <ref bean="myDateConverter"/>
            </set>
        </property>
    </bean>

<bean id="person" class="com.baizhiedu.converter.Person">
       <property name="name" value="涨三"/>
    <property name="birthday" value="1999-08-18"/>

</bean>

  1. 细节
  • MyDateConverter中的日期的格式,通过依赖注入的方式,由配置文件完成赋值
    MyDateConverter.java
package com.baizhiedu.converter;

import org.springframework.core.convert.converter.Converter;

import java.text.SimpleDateFormat;
import java.util.Date;

public class MyDateConverter implements Converter<String,Date> {
private  String pattern;

    public String getPattern() {
        return pattern;
    }

    public void setPattern(String pattern) {
        this.pattern = pattern;
    }

    /**
     * convert方法作用:String----->Date
     * SimpleDateFormat sdf=new SimpleDateFormat();
     * sdf.parset(String)---->Date
     * param:source 代表的是配置文件中  日期字符串<value>1999-08-18</value>
     * return :当把转换好的Date作为convert方法的返回值后,Spring自动的为birthday属性进行注入赋值
     * @param source
     * @return
     */
    @Override
    public Date convert(String source) {
        Date date=null;
        try{
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
         date = dateFormat.parse(source);
        } catch (Exception e){
            e.printStackTrace();
        }

        return date;
    }
}

applicationContext2.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"
      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-4.0.xsd
 ">

    <!--Spring创建MyDateConverter类型转换器-->
    <bean id="myDateConverter" class="com.baizhiedu.converter.MyDateConverter">
           <property name="pattern" value="yyyy-MM-dd"/>


            </bean>

    <!--用于注册类型转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <ref bean="myDateConverter"/>
            </set>
        </property>
    </bean>

<bean id="person" class="com.baizhiedu.converter.Person">
       <property name="name" value="涨三"/>
    <property name="birthday" value="1999-08-18"/>

</bean>

</beans >


  • ConversionServiceFactoryBean定义 id属性值 必须 是 conversionService
  • Spring 框架内置日期类型的转换器

日期格式:支持2020/05/03 不支持(2020-05-01)

<bean id="person" class="com.baizhiedu.converter.Person">
       <property name="name" value="涨三"/>
    <property name="birthday" value="1999/08/18"/>

</bean>

第十三章 后置处理Bean

BeanPostProcessor作用 :对Spring工厂所创建的对象,进行加工
AOP底层实现:
注意:BeanPostProcessor接口
xxx(){

}

  • 后置处理Bean的运行的原理分析
    在这里插入图片描述

程序员实现BeanPostProcessor规定接口中的方法
Object postProcessBeforeInitiallization(Object bean String beanName)
作用:spring创建完对象,并进行注入后,可以运行Before方法进行加工
获得Spring创建好的对象:通过方法的参数
最终通过返回值交给Spring框架

Object postProcessAfterInitiallizetion(Object bean String beanName)
作用:Spring执行完对象的初始化操作后,可以运行after方法进行加工
获得Spring创建好的对象:通过方法的参数
最终通过返回值交给Spring框架

实现中:
很少处理Spring的初始化操作:没有必要区分Before After,只需要实现其中的一个方法即可
注意:
postProcessBeforeInitiallization
return bean对象

  • BeanPostProcessor的开发步奏
  1. 类 实现 BeanPostProcessor 接口
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }


    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Categroy categroy = (Categroy) bean;
        categroy.setName("小可爱");
        return categroy;
    }
}
  1. Spring 的配置文件中进行配置
<bean id="myBeanPostProcessor" class="xxx.MybeanPostProcessor"/>
  1. BeanPostProcessor细节

BeanPostProcessor会对Spring工厂中所有的创建的对象进行加工。
所以做好加if(bean instanceof XXX)来判断

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }


    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {


     if(bean instanceof Categroy){   Categroy categroy = (Categroy) bean;
        categroy.setName("小可爱");}
        return bean;
    }
}

#AOP编程
第一章 静态代理模式
1.为什么需要代理设计模式
1.1问题

  • 在javaEE分层开发中,哪个层次对于我们来讲最重要。

DAO---->Service—>Controller
javaEE分层开发中,最重要的是Service层

  • Service层中包含了哪些代码?

Service层中=核心功能(几十行,上百行代码)+额外功能(附加功能)

  1. 核心功能
    业务运算
    DAO调用
  2. 额外功能
    2.1不属于业务
    2.2可有可无
    2.3代码量微小
    2.4 列如 ,事务,日志,性能。。。。。

在这里插入图片描述

  • 额外功能书写在Service层中好不好?
 Service层的调用者的角度来讲(Controller):需要在Service层书写额外功能。
         
 *软件设计者:Service层不需要额外的功能*
  • 现实生活中的解决方案
    在这里插入图片描述
  1. 代理设计模式
    1.1概念

    通过代理类,为原始类(目标)增加额外功能
    好处:有利于原始类的(目标)的维护

    1.2 名词解释

    1. 目标类 原始类
      指的是 业务类(核心功能—>业务运算 DAO调用)
    2. 目标方法,原始方法
      目标类(原始类)中的方法 就是目标方法(原始方法)
      3.额外功能(附加功能)
      日志 事务 性能

    1.3 代理开发的核心要素

    代理类=目标类(原始类)+额外功能+原始类(目标类)实现相同的接口
    房东---->public interface UserService{
    m1
    m2
    }
    UserServiceImpl implements UserService{
    m1------>业务运算 DAO调用
    m2
    }

    UseServiceProxy implements UserService{
    private UserServiceimpl UserService=new UserServiceimpl();
    m1
    m2

    }

1.4 编码
静态代理:为每一个原始类,手工编写一个代理类(.java .class)
在这里插入图片描述
1.5 静态代理存在的问题

  1. 静态类文件数量过多,不利于项目的管理
    UserServiceImpl UserServiceProxy
    OrderServiceImpl OrderServiceProxy
  2. 额外功能维护性差(麻烦)

第二章,spring的动态代理开发

  1. Spring动态代理的概念

概念:通过代理类为原始类(目标类)增加额外的功能
好处:利于原始类(目标类)的维护

  1. 搭建开发环境

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.8</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.3</version>
        </dependency>
  1. spring动态代理的开发
    1. 创建原始对象(目标对象)
public class UserServiceImpl implements UserService {
    @Override
    public void register(User user) {     System.out.println("UserServiceImpl.register  业务运算+DAO");
    }

    @Override
    public boolean login(String name, String password) {       System.out.println("UserServiceImpl.login")return  true;
    }
}

添加spring配置创建对象UserServiceImpl


<bean id="userService" class="com.baizhiedu.proxy.UserServiceImpl">

  1. 额外功能
    MethodBeforeAdvice接口

额外功能书写在接口的实现中,运行在原始的方法执行之前运行额外功能。


public class Before implements MethodBeforeAdvice {
    /**
     * 作用:需要把运行在原始方法执行之前运行的额外功能,写在before方法中
     */
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("-----method  before advice  log-------");
    }
}

配置文件

<bean id="before" class="com.baizhiedu.dymamic.Before"/>
  1. 定义切入点

切入点:额外功能加入位置

目的:由程序员根据自己的需要,决定额外功能加入给哪个原始方法
register
login

简单的测试:所有方法都做为切入点,都加入额外功能。

 <aop:config>
<!-- 所有的方法 ,都作为切入点,加入额外的功能 Login  register-->
        <aop:pointcut id="pc" expression="execution(* *(..))"/>
 </aop:config>
  1. 组装(2 3整合)
表达的含义:所有的方法  都加入  before的额外功能
<!--    组装:目的把切入点  与 额外功能进行整合-->
        <aop:advisor advice-ref="before" pointcut-ref="pc">
  1. 调用

目的:获的Spring工厂创建的动态代理对象,并且调用
ApplicationContext ctx=new ClassPathXmlApplicationContext("/applicationContext.xml");
注意:

  1. Spring的工厂通过原始对象的id值获得的是代理对象
  2. 获得代理对象后,可以通过生明接口类型,进行对象的存储
    com.baizhiedu.proxy.UserService userService = (com.baizhiedu.proxy.UserService)ctx.getBean("userService");

userService.login("")
userService.register("")

4.动态代理细节分析

Spring 框架在运行时,通过D动态字节码技术,在jvm创建的,运行在jvm内部,等程序的结束后,会和jvm一起消失

什么叫动态字节码技术:通过第三个动态字节码框架,在jvm中创建对应的类的字节码,进而创建对象,当虚拟机结束,动态字节码消失

结论:动态代理不需要自定义类文件,都是在jvm虚拟机运行过程中动态创建的,所以不会造成静态代理,类文件数量过多,影响项目管理问题。
在这里插入图片描述

  1. 动态代理编程简化代理开发
  1. 在额外功能不改变的前提下,创建其他目标类(原始类)的代理对象时,只需要指定原始(目标)对象即可。
  1. 动态代理的额外功能的维护性大大增强
第三章动态代理的详解
  1. 额外功能的详解
  • MethodBeforeAdvice分析(额外功能只能运行在原始方法之前)

public class Before1 implements MethodBeforeAdvice {
    /**
     *作用:需要把运行在原始方法执行之前运行的额外功能,书写在before方法中
     * Method:额外功能所增加给的那个原始法方法
     * login 方法
     * 
     * register 方法
     * 
     * showOrder方法
     * 
     * Object[]:额外功能所增加给的那个原始方法的参数,String name,String  password
     *                                            User
     * Object:额外功能所增加的那个原始对象   UserServiceImpl
     *                                   OrderServiceImpl
     */
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("-----new method  before advice  log-------");
    }
}

  1. before方法的3个参数在实战中,该如何使用

before 方法的参数,在实战中,会根据需要进行使用,不一定会用到,也有可能会用到
Servlet{ service(HttpRequest request,HttpResponse reponse){ request.getParameter("name")-----> response.getWriter()------->} }

  • MethodIntercepor(方法拦截 器)

methodinterceptor接口:额外功能可以根据需要运行在原始方法之前 或者之后或者前后


public class Arround implements MethodInterceptor {
    /**
     *invoke 方法的作用:额外功能书写在invoke
     *                 额外功能    原始方法之前
     *                             原始方法 之后
     *                             原始方法执行之前  之后
     * 确定:原始方法怎么运行
     * 参数:MethodInvocation  (Method):额外功能所增加给的那个原始的方法
     *                         login
     *                         register
     *       invocation.proceed()------>login运行
     *                                   register运行
     *  返回值:Object:原始方法的返回值
     *  Date  convert(String   name)
     */



    @Override
    public Object invoke(MethodInvocation Invocation) throws Throwable {
        System.out.println("----额外功能 log-----");
        Object ret = Invocation.proceed();
        return  ret;
    }
}

额外功能运行在原始方法执行之后


    @Override
    public Object invoke(MethodInvocation Invocation) throws Throwable {
       
        Object ret = Invocation.proceed();

        System.out.println("----额外功能 log-----");
        return  ret;
    }

额外功能运行在原始功能之前之后

什么样的额外功能,运行在原始方法之前 之后都要添加?
事务

    @Override
    public Object invoke(MethodInvocation Invocation) throws Throwable {
        System.out.println("----额外功能 前log-----");
        Object ret = Invocation.proceed();

        System.out.println("----额外功能 后log-----");
        return  ret;
    }

额外功能运行在原始功能抛出异常的时候

  1. 原始功能:
package com.baizhiedu.proxy;

public class UserServiceImpl implements UserService {
    @Override
    public void register(User user) {
        System.out.println("UserServiceImpl.register  业务运算+DAO");

        throw new RuntimeException("测试异常");
    }

    @Override
    public boolean login(String name, String password) {
        System.out.println("UserServiceImpl.login");

        return true;
    }
}

额外功能:

  @Override
    public Object invoke(MethodInvocation Invocation) throws Throwable {
       
        Object ret=null;
        try {
            ret = Invocation.proceed();
        }catch (Exception e) {
            
            System.out.println("----额外功能 后log-----");

            e.printStackTrace();
        }
        return  ret;
    }
}

配置文件

<?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:aop="http://www.springframework.org/schema/aop"
      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-4.0.xsd
  http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd


">

<bean id="userService" class="com.baizhiedu.proxy.UserServiceImpl"/>
<bean id="orderService" class="com.baizhiedu.proxy.OrderServiceImpl">


</bean>
<!--<bean id="before" class="com.baizhiedu.dymamic.Before"/>-->
<!--    <bean id="before" class="com.baizhiedu.dymamic.Before1"/>-->

  <bean id="arround" class="com.baizhiedu.dymamic.Arround"/>

    <aop:config>
<!--        所有的方法 ,都作为切入点,加入额外的功能 Login  register-->
        <aop:pointcut id="pc" expression="execution(* *(..))"/>
<!--    组装:目的把切入点  与 额外功能进行整合-->
        <aop:advisor advice-ref="arround" pointcut-ref="pc"/>


    </aop:config>
</beans >


MethodInterceptor影响原始方法的返回值

原始方法的返回值,直接作为invoke方法的返回值返回,MethodInterceptor不会影响原始方法的返回值



    @Override
    public Object invoke(MethodInvocation Invocation) throws Throwable {
        Object ret = Invocation.proceed();
        System.out.println("----额外功能 后log-----");
        return  ret;
    }

MethodInterceptor影响原始方法的返回值
Invoke方法的返回值,不要直接返回原始方法的运行结果即可。
    @Override
    public Object invoke(MethodInvocation Invocation) throws Throwable {
        Object ret = Invocation.proceed();
        System.out.println("----额外功能 后log-----");
        return  false;
    }
2.切入点详解
     切入点决定额外功能加入位置(方法)
     <aop:pointcut id="pc" expression="execution(* *(..))"/>------>匹配了所有的方法  a  b c
     1.execution()  切入点函数
     2.* *(..)切入点表达式
2.1 切入点表达式

1.方法切入表达式
在这里插入图片描述

* *(..)--->所有方法
* ----->修饰符  返回值
* ------>方法名
()----->参数表
  ..  --------->对于参数没有要求(参数有没有,参数有几个都行,参数是什么类型都行)
  • 定义login方法作为切入点

    * login(..)
    
    # 定义registter作为切入点
    * register(..)
    
  • 定义login方法且login方法有两恶搞字符串类型的参数,作为切入点

    * login(String ,String)
    
    #注意:非java.lang包中的类型,必须写全限定名
    * register(com.baizhiedu.proxy.User)
    
    # ..可以和具体的参数类型连用
    * login(String ,..)-----login(String),login(String,String),login(String,com.baizhiedu.proxy.User)
    
  • 精准方法的切入点限定
    在这里插入图片描述

在这里插入图片描述

修饰符   返回值         包. 类. 方法(参数)
*                                com.baizhiedu.proxy.UserServiceImple.login(..)
*                                   com.baizhiedu.proxy.UserServiceImpl.login(String,String)
  1. 类切入点

    在这里插入图片描述

    指定特定的类作为切入点(额外功能加入的位置),自然这个类中的所有的方法,都会加上对应的额外功能
    
  • 语法1

         #类中的所有的方法加入了额外功能
         *      com.baizhiedu.proxy.UserServiceImpl.*(..) 
    
  • 语法2
    在这里插入图片描述
    在这里插入图片描述

     # 忽略包
     1.类只有一级包 com。UserServiceImpl
     * *.UserServiceImpl.*(..)
     2. 类存在多级包   com.baizhiedu.proxy.USerServiceImpl
     3. * *..UserServiceImpl.*(..)
    
  1. 包切入点表达式 实战

    指定包作为额外功能加入的位置,自然包中的所有类以及其方法都会加入额外的功能
    
  • 语法1

    #切入点包中的所有类,必须在proxy中,不能再proxy包的子包中
    *  com.baizhiedu.proxy.*.*(..)
    
  • 语法2

      #切入点当前包,以及其子包都生效
      * com.baizhiedu.proxy..*.*(..)
    
2.2切入函数
 切入点函数:用于执行切入点表达式
  1. execution

    最为重要的切入点函数,功能最全
    执行  方法切入点表达式  类切入点表达式,包切入点表达式
       
    弊端:execution执行切入点的表达式,书写麻烦
      execution(*   com.baizhiedu.proxy..*.*(..))
       
       注意:其他的切入点函数  简化是execution书写复杂度,功能上完全一至
    
  2. args

      作用:主要用于函数(方法)参数匹配
           
       切入点:方法参数必须得是两个字符串类型得参数
       exectution(* *.(String,String))
             
         args(String,String);
    

3.within

  作用:主要用于进行类,包切入点表达式得匹配 
   
    切入点:UserServiceImpl这个类
     
     exection(* *..UserServiceImpl.*(..))
      
      within(*..UserServiceImpl)  
       
       execution(*  com.baizhiedu.proxy..*.*(..))
       
       within(com.baizhiedu.proxy..*)
  1. @annotation

     作用:为具有特殊注解的方法加入额外功能
      
              <aop:pointcut id="pc" expression="@annotation(com.baizhiedu.Log)"/>
    

自定义注解

package com.baizhiedu;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)
public @interface Log {


}

  1. 切入点函数的逻辑运算

    指的是 整合多个切入点函数一起配合工作,进而完成复杂的需求
    
  • and与操作

     案例:login 同时 参数 2个字符串
     1. excution(* login(String,String))
     2. excution(* login(..)and args(String,String))
        
        
    注意:与操作不同用于用于同种类型的切入点函数
     
       #案例:register 方法 和login方法作为切入点
       execution(* login(..))and execution(* register(. .))//错误
           execution(* login(..))or execution(* register(. .))
    
    • or 或操作

      #案例:register 方法 和login方法作为切入点
      
      execution(* login(..))or execution(* register(. .))  
      

第四章AOP编程

1.AOP概念

AOP(Aspect Oriented  Programing) 面向切面编程=Spring 动态代理开发
  
  以切面为基本单位的程序开发,通过切面编间的彼此协同,相互第哦啊用,完成程序的构造
  切面=切入点+额外功能
   
    
    OOP(Object  Oritened  Programing) 面向对象的编程 java
    以对象为基本单位程序开发,通过对象间的彼此协同,相互调用,完成程序的构建
     
      
      Pop(Producer  Oriented  Programing) 面向过程的(方法  函数) c语言 
      以过程为基本单位的程序开发,通过过程的间的彼此协同,相互调用,完成程序的构建。
 
      

Aop的概念:
   本质就是Spring得动态代理开发,通过代理类为原始类增加额外得功能
   好处:利于原始类得维护
注意:Aop编程不可代替oop,oop编程有意补充
2.Aop编程得开发步奏
 原始对象
 额外功能(MethodInterCeptor)
 切入点
 组装切面(额外功能+切入点)
3.切面得名词解释
切面=切入点+额外功能
 
  几何学
  面=点+相同的性质

在这里插入图片描述

第五章 Aop得底层实现得原理

  1. 核心问题

    1.Aop如何创建动态代理类(动态字节码技术)
    2.Spring工厂如何加工创建代理对象
        通过原始对象得id值,获得的是代理对象。
    
2. 动态代理的创建

2.1 JDk的动态代理

  • Proxy.newProxyInstance 方法参数的详解
    在这里插入图片描述
    在这里插入图片描述
  • 编码
import com.baizhiedu.proxy.User;
import com.baizhiedu.proxy.a.UserService;
import com.baizhiedu.proxy.a.UserServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestJDKProxy {
    /**
     * 1.借用类加载器  TestJDKProxy
     * UserServiceImpl
     * 2.Jdk8.x以前
     * final UserServiceImpl userService = new UserServiceImpl();
     */
    public static void main(String[] args) {
        //1.创建原始对象
        UserServiceImpl userService = new UserServiceImpl();
        //2.JDK创建动态代理
        /**
         *
         */
        InvocationHandler handler = new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("------proxy  log------");
                //原始方法运行
                Object ret = method.invoke(userService, args);
                return ret;
            }
        };

        UserService userServiceProxy = (UserService) Proxy.newProxyInstance(TestJDKProxy.class.getClassLoader(), userService.getClass().getInterfaces(), handler);

        userServiceProxy.login("login", "123456");
        userServiceProxy.register(new User());
    }
}

2.2 CGlib的动态代理

1.CGlib创建动态代理的原理:父子继承创建代理对象,原始类作为父类,代理类作为子类,这样既可以保证2者方法一致,同时在代理类中提供新的实现(额外功能+原始方法)

在这里插入图片描述

-CGlib编码

package com.baizhiedu.cglib;

import com.baizhiedu.proxy.User;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class TestCglib {

    public static void main(String[] args) {
        //创建原创对象
        UserService userService = new UserService();
        /**
         * 通用cglib方式创建动态代理对象
         * proxy。newProxyInstance(classloader,interface,invocationhandler)
         * Enhancer.setClassLoader();
         * Enhancer.setSuperClass();
         * Enhancer。setCallback();-----》MethodInterceptor(cglib)
         * Enhancer.create()---->代理
         *
         */

        Enhancer enhancer = new Enhancer();
        enhancer.setClassLoader(TestCglib.class.getClassLoader());
        enhancer.setSuperclass(userService.getClass());
        MethodInterceptor interceptor = new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("----cglib   log----");
                Object ret = method.invoke(userService, args);

                return ret;

            }
        };


        enhancer.setCallback(interceptor);
        UserService userServiceProxy = (UserService) enhancer.create();
    userServiceProxy.login("小可爱","123456");
    userServiceProxy.register(new User());


    }


}

  • 总结

    1.Jdk动态代理  Proxy.newProxyInstance() 通过接口创建的实现类
    2.Cglib动态代理  Enahancer  通过继承父类创建的代理类
    
  1. Spring工厂如何加工原始对象
  2. (Spring工厂对于代理的加工)
  • 思路分析
    在这里插入图片描述

  • 编码
    ProxyBeanPostProcessor.java

package com.baizhiedu.factory;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class PoxyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {



        return bean;

    }

    @Override
    /**
     * Proxy.newProxyInstance()
     */
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("-----new Log------");
                Object ret = method.invoke(bean, args);


                return ret;
            }
        };
        Object mm = Proxy.newProxyInstance(PoxyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), handler);


        return  mm;
    }
}

配置文件

<?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:aop="http://www.springframework.org/schema/aop"
      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-4.0.xsd
  http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd


">

<bean id="userService" class="com.baizhiedu.factory.UserServiceImpl"/>


<!--1.实现beanPostProcessor 进行加工-->
    <!--2.配置文件中对beanPostProcessor进行处理-->
<bean id="proxyBeanPostProcessor" class="com.baizhiedu.factory.PoxyBeanPostProcessor"/>






</beans >


在这里插入图片描述

第六章 基于注解的AOP编程

1.基于注解的开发步奏
 1.原始对象
 2.额外功能
 3.切入点
 4.组装切面
  
    
    #t通过切面类  定义了 额外功能 @Arround
                        定义了  切入点  @arround("execution( * login(..))")
                        @Aspect 切面类
package com.baizhiedu.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;


/**
 * 1.额外功能
 * public  Class MyArround implements MethodInterceptor{
 *     public  Object invoke(MethodInvocation  invocation){
 *      Object ret=   invocation.proceed();
 *      return ret;
 *     }
 *
 *
 * }
 * 2.切入点
 * <aop:config
 * <aop:pointcut  id="" expression="execution(* login(..))"/>
 * >
 * 3.组装
 */


@Aspect
public class MyAspect {

    @Around("execution(* login(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("---log-----");
        Object ret = joinPoint.proceed();

        return ret;
    }
}

注解

<?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:aop="http://www.springframework.org/schema/aop"
      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-4.0.xsd
  http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd


">

<bean id="userService" class="com.baizhiedu.factory.UserServiceImpl"/>

<!--切面
实现了

1.额外功能
2.切入点
3.组装
-->
<bean id="around" class="com.baizhiedu.aspect.MyAspect"/>

<!--告知spring基于注解进行aop编程-->
    <aop:aspectj-autoproxy/>
</beans >


加@Aspect注解的称为切面类
在这里插入图片描述

2.细节
  1. 切入点的复用
 切入点服用:在切面定义一个函数,上面@pointcut注解, 通过这种方式,定义切入点的表达式,后续更有利于切入点的 复用.


package com.baizhiedu.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;


/**
 * 1.额外功能
 * public  Class MyArround implements MethodInterceptor{
 *     public  Object invoke(MethodInvocation  invocation){
 *      Object ret=   invocation.proceed();
 *      return ret;
 *     }
 *
 *
 * }
 * 2.切入点
 * <aop:config
 * <aop:pointcut  id="" expression="execution(* login(..))"/>
 * >
 * 3.组装
 */


@Aspect
public class MyAspect {
@Pointcut("execution(* login(..))")
public  void myPointcut(){}
    @Around(value = "myPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("---log-----");
        Object ret = joinPoint.proceed();

        return ret;
    }
    @Around(value = "myPointcut()")
    public Object around1(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("---log  tx-----");
        Object ret = joinPoint.proceed();

        return ret;
    }
}

  1. 动态代理的创建方式

    Aop底层实现  2种代理的创建方式
    1.jdk  通过         实现接口  做新的实现类方式  创建代理对象
    2.  Cglib通过继承父类  做新的子类   创建动态代理对象
     # 
           默认情况下  Aop编程,低层应用的是JDK动态代理创建方式
       如果切换Cglib怎么做?
        <!--告知spring基于注解进行aop编程-->
      proxy-target-class="true"
    
1.基于Aop注解
<!--告知spring基于注解进行aop编程-->
 <aop:aspectj-autoproxy proxy-target-class="true"/>
 2.传统的Aop开发
     <aop:config proxy-target-class="true">
<!--        所有的方法 ,都作为切入点,加入额外的功能 Login  register-->
        <aop:pointcut id="pc" expression="@annotation(com.baizhiedu.Log)"/>
<!--    组装:目的把切入点  与 额外功能进行整合-->
        <aop:advisor advice-ref="arround" pointcut-ref="pc"/>
        
    </aop:config>

第七章 AOP开发的坑

 坑:在同一个业务种,进行业务方法间的相互相互调用,只有最外层的方法,才是加入了  额外功能(内部的方法,通过普通方式的第哦啊用,都调用的是原始的方法),如果想让人曾的方法也调用代理对象的方法,就要ApplicationContextAwrra 获得工厂,进而会的代理对象
package com.baizhiedu.aspect;

import com.baizhiedu.Log;
import com.baizhiedu.aspect.UserService;
import com.baizhiedu.basic.User;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;


public class UserServiceImpl implements UserService, ApplicationContextAware {
private ApplicationContext ctx;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.ctx=applicationContext;
    }
    @Log
    @Override
    public void register(User user) {

    System.out.println("UserServiceImpl.register  业务运算+Dao");
    //调用的是原始对象的Login方法--->核心功能
/**
 * 设计目的:代理对象的login方法--->额外功能+核心功能
 *ApplicationContext ctx= new ClassPathXmlApplicationContext("applicationContext4.xml");
 *           UserService userService=   (UserService)ctx.getBean("userService");
 * userService.login("sss","123");
 *
 */
        UserService userService =(UserService) ctx.getBean("userService");
        userService.login("sss","123");

    }
    @Log
    @Override
    public boolean login(String name, String password) {

        System.out.println("UserServiceImpl.login");
        return true;
    }


}


配置文件

<?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:aop="http://www.springframework.org/schema/aop"
      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-4.0.xsd
  http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd


">

<!--<bean id="userService" class="com.baizhiedu.proxy.a.UserServiceImpl"/>-->
<!--<bean id="orderService" class="com.baizhiedu.proxy.OrderServiceImpl"/>-->
<bean id="userService" class="com.baizhiedu.aspect.UserServiceImpl">

</bean>
<!--<bean id="before" class="com.baizhiedu.dymamic.Before"/>-->
<!--    <bean id="before" class="com.baizhiedu.dymamic.Before1"/>-->

  <bean id="arround" class="com.baizhiedu.dymamic.Arround"/>

    <aop:config proxy-target-class="true">
<!--        所有的方法 ,都作为切入点,加入额外的功能 Login  register-->
        <aop:pointcut id="pc" expression="@annotation(com.baizhiedu.Log)"/>
<!--    组装:目的把切入点  与 额外功能进行整合-->
        <aop:advisor advice-ref="arround" pointcut-ref="pc"/>


    </aop:config>
</beans >


Aop第八章 总结

在这里插入图片描述

Spring与持久层整合

第一章 持久层整合

  1. Spring为什么要与持久层整和?

    1.javaEE 开发需要持久层进行数据库的操作
    2.jdbc Hibernate Mybatis 惊醒持久开发的过程存在大量的代码庸于
    3.spring基于模板设计模式 对于上述的持久层技术进行了封装
    
  2. Spring可以与那些持久层技术进行整合
    在这里插入图片描述

第二章

  1. mybatis 开发步奏的回顾
    在这里插入图片描述

  2. mybatis 在开发过程中存在的问题

    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210421203632532.png)
    
  3. Spring整合思路
    在这里插入图片描述

spring 与Mybatis整合的开发步骤

<!--只需要配置一次-->
    <bean id="dataSource" class=""/>
    <!-- 创建SqlSessionFactory-->
    <bean id="ssfd" class="SqlSessionFactoryBean">
       <property name="dataSource" ref=""/> 
               
        <property name="typeAliasesPackage">
<!--                指定 实体类所在的包 com.baizhiedu.mybatis.User -->
        
        </property>
        
        <property name="mapperLocations">
<!--            指定 配置文件(映射文件)的路径 还有通用配置-->
            com.baizhiedu.mapper/*Mapper.xml
        </property>
    </bean>
    
    <!--DAO接口的实现类
    session========>session.getMapper()======>xXXXDAO实现类对象
    XXXDAO====>xxxDAO
    -->
    <bean id="scanner" class="MapperScannerConfigure">
        <property name="sqlSessionFactoryBeanName" value="ssfd"/>
        <property name="basePacakge">
            指定 DAo接口放置的包  com.baizhiedu.dao
        </property>
        
        
    </bean>
  • 编码

     1. 实体
     2. 表
     3. 3.创建DAO接口
     4. 实现Mapper文件    
    
  • pom.xml

 <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
 </dependency>
 
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>

   </dependency> 
   <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
         <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
            <scope>compile</scope>
        </dependency>
<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.9</version>
        </dependency>
  • 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 id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/suns?characterEncoding=utf8&amp;serverTimezone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>
    <!-- 创建SqlSessionFactory  SqlsessionFactoryBean-->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="typeAliasesPackage" value="com.baizhiedu.entity">
            <!--                指定 实体类所在的包 com.baizhiedu.mybatis.User -->
        </property>

        <property name="mapperLocations">
            <!--            指定 配置文件(映射文件)的路径 还有通用配置-->
            <!--            com.baizhiedu.mapper/*Mapper.xml-->
            <list>
                <value>classpath:com.baizhiedu.mapper/*Mapper.xml</value>
            </list>
        </property>
    </bean>

    <!--DAO接口的实现类
    session========>session.getMapper()======>xXXXDAO实现类对象
    XXXDAO====>xxxDAO
    -->
    <bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
        <property name="basePackage" value="com.baizhiedu.dao">
            <!--            指定 DAo接口放置的包  com.baizhiedu.dao-->
        </property>
    </bean>
    <bean id="userService" class="com.baizhiedu.service.UserServiceImpl"/>
</beans>
  1. Spring与mybatis的整合细节

在这里插入图片描述

第三章Spring的事务处理

  1. 什么是事务?
    在这里插入图片描述

  2. 如何控制事务?
    在这里插入图片描述

  3. Spring控制事务的开发
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  4. spring控制事务的编码

  • 搭建开发环境

    <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
          <version>5.1.14.RELEASE</version>
      </dependency>
    
  • 编码

  <bean id="userService" class="com.baizhiedu.service.UserServiceImpl">

        <property name="userDao" ref="userDao"/>
    </bean>

    <!--spring提供的 配置额外功能的方法  增加事务
    DateSourceTransactionManage
    -->
    <bean id="dateSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
    </bean>




    <!--配置切入点   额外功能加入切入点-->
    <tx:annotation-driven transaction-manager="dateSourceTransactionManager"></tx:annotation-driven>

service.java

package com.baizhiedu.service;

import com.baizhiedu.dao.UserDao;
import com.baizhiedu.entity.User;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public class UserServiceImpl implements  UserService {

   private UserDao userDao;

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void register(User user) {
userDao.save(user);
    }
}

  • 细节
    <!--配置切入点   额外功能加入切入点-->
    <tx:annotation-driven transaction-manager="dateSourceTransactionManager" proxy-target-class="true"/>
//其中的true  flase 控制着jdk 代理和cglib代理的切换
默认: false jdk
       true  Cglib

Spring 的事务属性(transaction Attribute)

1. 什么是事务属性

在这里插入图片描述

2. 如何添加事务属性

在这里插入图片描述

3.事务属性的详解
  • 隔离属性的概念

在这里插入图片描述

  • 事务并发产生的问题

    • 脏读

      一个四和五,读取了另一个事务中国没有提交的数据,会在本事务中产生数据不一致的问题
      解决方案:@transactional(isolation = Isolation.READ_COMMITTED)
      
    • 不可重复读

        一个事务中,多次读取相同的数据,但是读取结果不一样,会在本事务中产生数据不一致的问题
        注意:1.不是脏读2.一个事务中
        解决方案:isolation = Isolation.REPEATABLE_READ
        本质:一把行锁
      

在这里插入图片描述

  • 幻读

    一个事务中,多次对整表进行查询统计,但是结果不一样,会在本事务中产生数据不一致的问题.
    解决方案:isolation = Isolation.SERIALIZABLE
    本质:表锁.
    

    在这里插入图片描述

- 总结

在这里插入图片描述

事务属性

- 数据库对隔离属性的 支持

在这里插入图片描述

  • 默认的隔离属性

    ISOLATION_DEFAULT 会调用不同数据库的默认隔离级别属性
    Mysql:REPEATABLE_READ
    Oracle:READ_COMMETTED
    
  • 查看数据库的默认隔离级别

在这里插入图片描述

  • 隔离属性(建议使用默认值)
    在这里插入图片描述
  1. 传播属性

在这里插入图片描述

2.1  事务嵌套视图:

在这里插入图片描述

- 传播属性的值 及其用法

在这里插入图片描述

  • Required
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • Supports
    在这里插入图片描述

  • 默认的传播属性

    required是传播属性的默认值
    
  • 推荐传播属性的使用方法

     增 删改方法:直接使用默认值的required
     查询 操作:显示指定传播属性的值为supports
    
  • requires_new

在这里插入图片描述

  1. 只读属性(readOnly)(用于快速查找增加速度)

     针对只进行查询的操作的业务方法,可以加入只读属性,提高运行效率
     默认值为false
    
@Transactional(isolation = Isolation.SERIALIZABLE)
public class UserServiceImpl implements  UserService {

   private UserDao userDao;

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void register(User user) {
userDao.save(user);
//throw  new RuntimeException("测试");//这个如果抛出异常 那么save()失败,说明加事务成功,
    }

    /**
     *查询时用事务中的这两个方法,会事半功倍
     * 
     * @param name
     * @param password
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
    public void login(String name, String password) {

    }
}

在这里插入图片描述

  1. 超时属性

    指定了事务等待的最长时间
      1. 为什么事务进行等待?
         当前事务的访问数据时,有可能访问的数据被别的事务进行加锁的处理,那么此时的事务就必须进行等待.
       2. 等待时间为秒数
       3. 如何应用 @Transactional(timeout=2);
       4. 超时属性的默认值 -1
          最终由对应的数据库来指定
    
@Transactional(timeout = 2)
public class UserServiceImpl implements  UserService {

   private UserDao userDao;

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void register(User user) {
 //定义超时属性 
        try{Thread.currentThread().sleep(Long.parseLong("3000"));
userDao.save(user);}catch (Exception e){
            e.printStackTrace();
        }
//throw  new RuntimeException("测试");//这个如果抛出异常 那么save()失败,说明加事务成功,因为复合事务的一致性
    }

    /**
     *查询时用事务中的这两个方法,会事半功倍
     *
     * @param name
     * @param password
     */
    @Override

    public void login(String name, String password) {

    }
}
  1. 事务的异常属性

    Spring事务处理过程中
    默认 对于RuntimeException 及其子类 采用的是回滚的策论
    默认 对于Exception以其子类 采用的是提交的策略
    rollbackFor=(java.lang.Exception.xxx.xxx)
    noRollbackFor={java.lang.RuntimeException.xxx.xx}

    @Transactional(rollbackFor ={java.lang.Exception.class} ,noRollbackFor = {java.lang.RuntimeException.class})
      
      建议:实战中使用RuntimeException={及其子类,使用事务异常属性的默认值.}
    

在这里插入图片描述

4. 事务属性常见配置总结

在这里插入图片描述

5.基于标签的事务配置方式(事务开发的第二种方式)
基于注解@Transaction的事务配置回顾
第一原始对象
 <bean id="userService" class="com.baizhiedu.service.UserServiceImpl">

        <property name="userDao" ref="userDao"/>
    </bean>

    <!--spring提供的 配置额外功能的方法 增加事务
    DateSourceTransactionManage
    -->
    第二额外功能
    <bean id="dateSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
    </bean>
 
  ///切入点
    <!--配置切入点   额外功能加入切入点-->
    @Transactionnal(isolation=,propagation=....)
    public class UserServiceImpl implements UserService{
   private UserDao userDao
   
    ///切入点与 额外功能完美整合
    <!--额外功能,与注解完美的整合-->
    <tx:annotation-driven transaction-manager="dateSourceTransactionManager" proxy-target-class="true"/>
   事务属性
   <tx:advice id="txAdvice" transacation-manager="dataSourceTransactionManager">
<tx:method name="register" isoloation="",propagation=""> </tx:method>
<tx:method name="login" ......></tx:method>
等效于
@Transactional(isolation=,propsgation=)
public  void register(){

}

      </tx:advice>
<aop:config>
//切入点
<aop:pointcut id="pc" epression="execution(* com.baizhidu.service.USerServiceImpl.regist(..))">
</aop:pointcut>
//组装
<aop:advisor advice-ref="txtAdvice" pointcut-ref="pc">
</aop:advice>
</aop:config>
    
  • 基于标签的事务配置在实战中的应用(service包哪个方法,或者类加@Transactional 就会在哪个类或者方法上加上事务,以及所配置 的属性)
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd



">

   <bean id="dateSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
    </bean>

<!--<tx:advice id="txAdvice" transaction-manager="dateSourceTransactionManager">-->
<!--        <tx:attributes>-->
<!--            <tx:method name="register" isolation="DEFAULT" propagation="REQUIRED"/>-->
<!--        </tx:attributes>-->
<!--</tx:advice>-->
<!--编程的时候 service包中负责进行增删改操作的方法,都以modify开头
 查询操作,命名无所谓
 -->
    <tx:advice id="txAdvice" transaction-manager="dateSourceTransactionManager">
        <tx:attributes>
            <!--代表以modify开头的增删改的方法会添加事务的指定属性-->
            <tx:method name="modify*" />
            <!--除了除了增删改其他用modify开头,其他用什么命名无所谓-->
            <tx:method name="*" isolation="DEFAULT" read-only="true" propagation="REQUIRED"/>

        </tx:attributes>
    </tx:advice>

<!--<aop:config>-->
<!--    <aop:pointcut id="pc"  expression="execution(* com.baizhiedu.service.UserServiceImpl.register(..))"/>-->

<!--    <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>-->
<!--</aop:config>-->

<!--   应用的过程中,service放置到service包中-->
    <aop:config>
        <aop:pointcut id="pc"  expression="execution(* com.baizhiedu.service..*.*(..)"/>

        <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
    </aop:config>

pom.xml文件配置

 <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.1.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.18</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>

在这里插入图片描述

spring 和mvc整合

第一章 mvc框架整合思想

1. 搭建web运行环境
<dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.2.4.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.2.4.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>5.2.4.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.20</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.25</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.2</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.1.14.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.3</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.18</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.15</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.6</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
2. 为什么要整合mvc框架
     1.mvc框架提供了控制器(Controller)调用Service
      dao----》service
      2.请求响应的处理
      3.接受请求的参数 request。getParameter(“”)
      4.控制程序的运行流程
      5.视图解析(jsp  json freemarker  Thyemeleaf)
3. spring可以整合哪些mvc框架?
        1.struts1
        2.webwork
        3.jsf
        4.struts2
        5.springmvc
4. spring 整合mvc框架的核心思想
  1. 准备工厂

在这里插入图片描述

在这里插入图片描述

  1. 代码整理
    在这里插入图片描述
3. Spring 开发过程中多配置文件的处理

在这里插入图片描述

  • 通配符方式
    在这里插入图片描述

    • <import标签

       applicationContext.xml  目的 整合其他配置内容
       <import resource="applicationContext-dao.xml"/>
       <import resource="applicationContext-service.xml"/>
       <import resource="applicationContext-action.xml"/>
        
        1.非web环境
        new  ApplicationContext ctx=
        ClassPathXMLApplicationContext("/applicationContext.xml");
        2.web环境下
        <context-param>
        <param-name>contextConfigLocation</param-name>  
        <param-value>  classpath:applicationContext.xml</param-value>
        </context-param>
      

在这里插入图片描述

Spring注解编程

第一章

1. 什么是注解编程在这里插入图片描述
2.为什么要讲注解注解编程?

在这里插入图片描述

3. 注解的作用
  • 替换xml这种配置形式,简化配置
    在这里插入图片描述

  • 替换接口,实现调用双方的契约性

    通 过注解的方式,在功能调用者和功能的提供者之间达成的达成的约定,进而进行功能的调用,因为注解应用更为灵活,所以现在的开发中,更加推荐通过注解的形式,完成。
    

在这里插入图片描述
在这里插入图片描述

4.spring注解的发展历程

在这里插入图片描述

5.注解开发的问题

在这里插入图片描述

第二章,spring的基础注解(Spring2.x)

在这里插入图片描述

1.对象创建相关注解
  • 搭配开发环境
    applicationContext.xml
<context:component-scan base-package="com.baizhiedu"/>
作用:让spring框架在设置包以及子包中扫描对应的注解,使其生效。
  • 对象相关的注解

    • @Component

       作用:替换原有spring配置 配置的文件中的<bean标签
       注意:
       id属性 component注解 提供了默认的设置方式,首单词字母单词小写,Class属性  通过反射获得class 内容
      

在这里插入图片描述

  • @Component 细节

    • 如何显示指定工厂创建对象的id值

      @Component("u")
      
    • Spring配置文件覆盖注解配置内容

       applicationContext.xml
       <bean id="u" class="com.baizhiedu.bean.User"/>
        
        id值  class的值 要和 注解中的设置保持一致。否则就会创建一个新的值
      
    • @Component的衍生注解

      在这里插入图片描述

    • @Scope注解

         //@Scope("singleton")
           @Scope("prototype") 
      

在这里插入图片描述

  • @lazy
    在这里插入图片描述
  • 生命周期相关的注解
    在这里插入图片描述
package com.baizhiedu.life;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class Product {
@PostConstruct
// scope为默认值时工厂创建之后被调用
    public  void myInit(){
    System.out.println("Product.myInit");
}
@PreDestroy
//工厂关闭之前被调用
    public void myDestory(){
    System.out.println("Product.myDestory");
}


}

2.注入相关注解
  • 用户自定义注入类型@Autowired

    加入注解前 在这里插入图片描述
    加入注解后
    在这里插入图片描述

    @Autowired 细节【推荐】
     1.Autowired 注解基于类型进行注入
             基于类型的注入:注入对象的类型,必须与目标成员变量类型相同或者是其子类(实现类)
    

在这里插入图片描述

     Autowired Qualifier 基于名字注入【了解】
       基于名字的注入:注入对象的id值,必须与qualifier注解中设置的名字相同

在这里插入图片描述
在这里插入图片描述

3.autowired注解放置位置

a)放置在对应成员变量的set方法上 
spring会通过set方法为成员变量赋值

b)直接放置在这个放在成员变量上,
Spring通过反射直接对成员变量进行注入(赋值)【推荐】

在这里插入图片描述

 4.javaEE规范中类似功能的注解
 JSR250 @Resouce(name="userDAoImpl") 基于名字进行注入
   等同 =    @Autowired()
             @Qualifier("userDAoImpl")
        注意:如果在应用Resource注解时,名字没有配对成功,那么他会继续按照类型进行注入

总结 在这里插入图片描述

  • jdk类型

在这里插入图片描述

在这里插入图片描述

-@ PropertySource

在这里插入图片描述

 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210424231441669.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzUyOTQ2MTA0,size_16,color_FFFFFF,t_70)
  • @value注解使用细节
    • @value注解不能应用在静态成员变量上

      如果应用,赋值(注入)失败
      
    • @value注解+Properties这种方式,不能注入集合类型

       Spring提供新的配置形式  YAML YML(springBoot)
      

3.注解扫描详解

   <context:component-scan base-package="com.baizhiedu"/>
   当前包  以及  子 包
1.排除方式
<context:component-scan base-package="com.baizhiedu">
<context:exclude-filter type=""  expression=""/>
  type:assignable:排除特定的类型  不进行扫描
     annotation: 排除特定的注解 不进行扫描
     aspectj:切入点表达式
                    包切入点:com.baizhiedu.bean..*
                    类切入点:*..User
       regex:正则表达式
       custom:自定义排除策略框架底层开发
      
</context:component-scan>
 
 
排除策略可以叠加使用
 <context:component-scan base-package="com.baizhiedu">
    <!--排除指定id的注解-->
    <context:exclude-filter type="assignable" expression="com.baizhiedu.bean.User"/>
<!--排除指定类型的注解-->
<!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>-->

<!--排除指定包下的或者类不去扫描,通过切入点表达式-->
<!--    <context:exclude-filter type="aspectj" expression="com.baizhiedu.injection..*(..)"/>
-->
    
    <context:exclude-filter type="aspectj" expression="*..User"/>
  </context:component-scan>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 包含方式

在这里插入图片描述

在这里插入图片描述

4.对于注解开发的思考

  • 配置互通
    在这里插入图片描述
  • 什么情况下使用注解 什么情况下使用配置文件
    在这里插入图片描述
  1. ssm整合开发 (半注解)
  • 搭建环境
    在这里插入图片描述

  • 编码

    • Dao(spring+mybatis)
      在这里插入图片描述

    • Service(Spring添加事务)
      在这里插入图片描述

    • Controller (Spring+struts2)
      在这里插入图片描述
      在这里插入图片描述

第三章。spring 的高级注解(spring3.x及以上)

  1. 配置bean

在这里插入图片描述

  1. 配置bean在应用的过程中 替换了xml具体什么内容呢?

在这里插入图片描述

  1. AnnotationCoinfig ApplicationContext

在这里插入图片描述

在这里插入图片描述

  • 配置Bean开发的细节分析

    • 基于注解开发使用日志

      1.不能集成Log4j
      2.集成logback
      
      • 引入相关的jar包
<dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.25</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
            <scope>compile</scope>
        </dependency>


        <dependency>
            <groupId>org.logback-extensions</groupId>
            <artifactId>logback-ext-spring</artifactId>
            <version>0.1.4</version>
        </dependency>
  • 引入logback配置文件(logback.xml)
<?xml version="1.0" encoding="UTF-8"?>

<!-- 配置文件修改时重新加载,默认true -->
<configuration >


    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder charset="UTF-8">
            <!-- 输出日志记录格式 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration >
  • @Configuration注解的本质
    在这里插入图片描述
  1. @Bean注解

在这里插入图片描述
3. @Bean注解的基本使用

  • 对象的创建
    在这里插入图片描述
    在这里插入图片描述
  • @Bean注解创建复杂对象的注意事项

在这里插入图片描述
ConnectionFactoryBean.java

package com.baizhiedu.bean;

import org.springframework.beans.factory.FactoryBean;

import java.sql.Connection;
import java.sql.DriverManager;

public class ConnectionFactoryBean implements FactoryBean {


    @Override
    public Object getObject() throws Exception {

        Class.forName("com.mysql.cj.jdbc.Driver");
       Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/suns?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone = GMT", "root", "123456");
        return conn;
    }

    @Override
    public Class<?> getObjectType() {
        return Connection.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

AppConfig.java(此处是加了@Configuration注解的类,相当于,applicationContext.xml)

package com.baizhiedu;

import ch.qos.logback.core.db.DriverManagerConnectionSource;
import com.baizhiedu.bean.ConnectionFactoryBean;
import com.baizhiedu.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.sql.Connection;
import java.sql.DriverManager;

@Configuration
public class AppConfig {
@Bean
    public User  user(){
    return  new User();
}
@Bean
public Connection conn(){

    Connection conn=null;
    try{
        Class.forName("com.mysql.cj.jdbc.Driver");
        conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/suns?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone = GMT", "root", "123456");
    }catch (Exception e){
        e.printStackTrace();
    }
    return  conn;
}
@Bean
//复杂对象Connection已经在ConnectionFactoryBean中创建好,所以此处是创建的简单对象,对
//复杂对象的调用
    public Connection conn1(){
    Connection conn=null;
    try {
       ConnectionFactoryBean factoryBean = new ConnectionFactoryBean();
        conn = (Connection) factoryBean.getObject();
   }catch (Exception e){
       e.printStackTrace();
   }
    return conn;
}
}

  • 自定义id值
    在这里插入图片描述
  • 控制对象的创建次数
    在这里插入图片描述
  1. @Bean注解的注入
  • 用户自定义类型

在这里插入图片描述

@Configuration
public class AppConfig1 {
    @Bean
    public UserDAo userDAo() {

        return new UserDAoImpl();
    }

    @Bean("u")
    public UserService userService(UserDAo userDAo) {

        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDAo(userDAo);

        return userService;
    }
}


    //方法二(简化写法)
    @Bean
    public UserService userService(){

        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDAo(userDAo());
        return userService;
  • JDK类型的注入(与自定义类型的区别是一个要定义形参,一个不用定义)
    在这里插入图片描述
package com.baizhiedu.bean;

public class Customer {
    private Integer id;
    private String name;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

  • jdk类型注入的细节分析
如果直接在代码中进行set方法的注入,会存在偶和


@Configuration
@PropertySource("classpath:/init.properties")
public class AppConfig1 {
    @Value("${id}")
    private Integer id;
    @Value("${name}")
    private String name;
    @Bean
    public UserDAo userDAo() {

        return new UserDAoImpl();
    }
 
  @Bean
    public Customer customer(){

        Customer customer = new Customer();
        customer.setId(id);
        customer.setName(name);

        return  customer;
    }
    
  1. @ComponentScan注解

在这里插入图片描述

在这里插入图片描述

  1. 基本使用

    @Configuration
    @ComponentScan(basePackages = “com.baizhiedu.scan”)
    public class AppConfig3 {
    }

    等同于
    <context:component-scan base-package=""/>

  2. #####排除,包含的使用

  • 排除
    在这里插入图片描述

单排除
在这里插入图片描述

多排除的同时使用
在这里插入图片描述

@Configuration
@ComponentScan(basePackages = "com.baizhiedu.scan",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class}),

@ComponentScan.Filter(type =FilterType.ASPECTJ,pattern = "*..User1")})
public class AppConfig3 {

}

  • 包含

在这里插入图片描述

在这里插入图片描述

@Configuration
@ComponentScan(
        basePackages = "com.baizhiedu.scan",
        useDefaultFilters = false,
        includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Service.class})}
)
public class AppConfig3 {

}

4. Spring工厂创建对象的多种配置方式

  1. 多种配置方式的应用场景
    在这里插入图片描述

  2. 配置文件的优先级
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 解决基于注解进行配置的接偶和问题

在这里插入图片描述


appliacationContext.xml 为了解耦合不在AppConfig5中使用
而改到AppConfig6中去添加这个注解,其实得到的效果和在 AppConfig5中添加起到的效果一样,但是前者起到了 解饿偶和的作用


@Configuration
//@ImportResource("applicationContext.xml")
public  class AppConfig5 {

@Bean
  public UserDAo userDAo(){
    return new UserDAoImpl();
}
}




@Configuration
@ImportResource("applicationContext.xml")
public  class AppConfig6 {


}



    @Test
    public void test8(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig5.class,AppConfig6.class);
        UserDAo userDAo = ctx.getBean("userDAo", UserDAo.class);
        userDAo.save();

    }







applicationContext.xml

只需写一个bean标签覆盖并且别创建新的实现类
    <bean id="userDAo" class="com.baizhiedu.injection.UserDAoImplNew"/>

5. 整合多个配置信息

  • 为什么会有多个配置信息

在这里插入图片描述

在这里插入图片描述

  • 多配置信息的整合方式

    • 多个配置Bean的整合
    • 配置Bean与@Component相关注解的整合
    • 配置Bean与SpringXML配置文件的整合
  • 整合多种配置需要关注哪些要点?

    • 如何使用配置的信息 汇总成一个整体
    • 如何实现夸配置的注入
    1. 多个配置bean的整合
    • 多配置的信息汇总

      • base-package进行多个配置bean的整合

      在这里插入图片描述

      • @import

         1.可以创建对象
         2.多配置bean的整合
        

      在这里插入图片描述

      • 在工厂创建时,指定多个配置Bean的Class对象

      在这里插入图片描述

    • 夸配置进行注入(讲另一个配置文件的bean注入到当下的配置文件中来)

@Configuration
@Import(AppConfig2.class)
public class AppConfig1 {
    @Autowired
    private UserDAo userDAo;
    @Bean
    public UserService userService(){
        UserService userService = new UserServiceImpl();
        ((UserServiceImpl) userService).setUserDAo(userDAo);
        return  userService;
    }
}




@Configuration
public class AppConfig2 {
   @Bean
    public UserDAo userDAo(){
       UserDAo userDAo = new UserDAoImpl();
       return userDAo;
   }
}

2.配置Bean与@Component相关注解的整合

在这里插入图片描述

3. 配置Bean与配置文件整合

在这里插入图片描述

6,。配置Bean底层实现原理

在这里插入图片描述

在这里插入图片描述

7.思维一体的开发思想

在这里插入图片描述

1.什么是四维一体
在这里插入图片描述
2. 四维一体是的开发案例

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
3.
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

8.纯注解版AOP编程

1.搭建环境

1.应用配置Bean
2.注解扫描

2.开发步奏

在这里插入图片描述

在这里插入图片描述
3.注解Aop细节分析

1.代理创建方式的切换 jdk  cglib
   <aop:aspectj-autoproxy  proxy-target-class=true|false/>
   @EnableAspectAutoProxy(proxyTargetClass)
2. springBoot Aop的开发方式
     @EnableAspectAutoProxy  已经设置好了
//1.原始对象

@Service
public class UserServiceImpl implements UserService {
    @Override
    public void register() {
        System.out.println("UserServiceImpl.register");
    }

    @Override
    public void login() {
        System.out.println("UserServiceImpl.login");
    }
}
 //2.创建切面 (额外功能 切入点 组装切面)
 @Aspect
@Component
public class MyApsect {
    @Pointcut("execution(* com.baizhiedu.aop..*.*(..))")
public  void pointCut(){}
    @Around("pointCut()")
public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("------log-----");
    Object proceed = joinPoint.proceed();
    return proceed;
}
}

spring Aop 代理默认实现是jdk spring Boot 代理默认实现Cglib

9. 纯注解版Spring+mybaitis

  • 基础配置(配置Bean)

```bash
1. 链接池
<!--链接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="root"></property>
<property name="username" value="root"></property>
</bean>
   @Bean
   public DruidDataSource dataSource(){
   DruidDataSource dataSource=new DruidDataSource();
   dataSource.setDriverClassName("");
   datasource.setUrl();
   ....
   return dataSource;
   }
   
2. SqlSeesionFactoryBean
<!--创建SqlSessionFactory SqlSessionFactoryBean-->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="typeAliasesPackage" value="com.baizhiedu.entity"/>
<property name="mapperLocations">
<list>
<value>classpath:com.baizhiedu.mapper/*Mapper.xml</value>
</list>

</property>

</bean>

@Bean
public SqlSessionFactoryBean(DataSource dataSource){

SqlSwssionFactoryBean sqlSessionFactoryBean=new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setTypeAliasesPackage("";
...
return sqlSessionFactoryBean;

}


3. MapperScannerConfigure
<!--创建DAO对象 MapperScannerConfigure-->
<bean id="scanner" class="org.mybatis.spring.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName"value="com.baizhiedu.dao"></property>

</bean>


@MapperScan(basePackages={"com.baizhiedu.dao"})---->配置bean中完成
  • 编码

    1. 实体
    2. DAO接口
    3. Mapper文件
1. MapperLocations编码时通配的写法
//设置Mapper文件的路径
sqlSessionFactoryBean.setMapperLocations(Resource..);

Resource  resource=new ClassPathResouce("UserDAOMapper.xml")
sqlSessionFactoryBean.setMapperLocations(new ClassPathResource("UserDAoMapper.xml"));



<property name="mapperLocations">
<list>
<value>classpath:com.baizhiedu.mapper/*Mapper.xml</value>
</list>
</property>

一组mapper文件
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        Resource[] resources = resolver.getResources("com.baizhiedu.mapper/*Mapper.xml");
        sqlSessionFactoryBean.setMapperLocations(resources);

2.配置Bean数据偶和问题

mybatis.driverClassName=com.mysql.cj.jdbc.Driver
mybatis.url=jdbc:mysql://localhost:3306/suns?useSSl=false&serverTimezone=UTC
mybatis.username=root
mybatis.password=123456
mybatis.typeAliasesPackages=com.baizhiedu.mapper/*Mapper.xml




@Component
@PropertySource("classpath:mybatis.properties")
public class MybatisProperties {
   @Value("${mybatis.driverClassName}")
    private  String driverClassName;
   @Value("${mybatis.url}")
    private String url;
   @Value("${mybatis.username}")
    private String username;
    @Value("${mybatis.password}")
    private String password;
    @Value("${mybatis.typeAliasesPackages}")
    private String typeAliasesPackages;
    @Value("${mybatis.mapperLocations}")
    private String mapperLocations;






@Configuration
@ComponentScan(basePackages = "com.baizhiedu.mybatis")
@MapperScan(basePackages = "com.baizhiedu.mybatis")
public class MybatisAutoConfiguration {
    @Autowired
    private  MybatisProperties mybatisProperties;
    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(mybatisProperties.getDriverClassName());
        dataSource.setUrl(mybatisProperties.getUrl());
        dataSource.setUsername(mybatisProperties.getUsername());
        dataSource.setPassword(mybatisProperties.getPassword());
        return dataSource;
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DruidDataSource dataSource) {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setTypeAliasesPackage(mybatisProperties.getTypeAliasesPackage());


        //  sqlSessionFactoryBean.setMapperLocations(new ClassPathResource("UserDAoMapper.xml"));

       try{ PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        Resource[] resources = resolver.getResources(mybatisProperties.getMapperLocations());
        sqlSessionFactoryBean.setMapperLocations(resources);}
       catch (Exception e){
           e.printStackTrace();
       }
        return sqlSessionFactoryBean;

    }
}

 ###### 10.纯注解版事务编程

在这里插入图片描述

    1. AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("com.baizhiedu.mybatis");
    SpringBoo实现思想
    2. SpringMybatis--->Dao 事务基于注解 ---》Service Controller
    org.springframework.web.context.ContextLoaderListender--->XML工厂  无法提供 new AnnotationConfigApplicationContext

11. spring 框架中yml的使用

  1. 什么是yml

        YML(YAML)是一种新形势的配置文件,比xml更加简单,比Properties更加强大
    
  2. Properties进行配置问题

     1. Properties表达过于繁琐,无法表达数据的内在联系
     2. Properties 无法表达对象  集合类型
    

在这里插入图片描述

  1. YML语法简介

    1. 定义yml文件
    xxx.yml  xxx.yaml
    2. 语法
         
          1. 基本语法
              name:suns
              password:123456 
           2. 对象概念
            account:
                id:1
                password:123456
           3. 定义集合
             service:
                - 1111
                - 2222
    
  2. Spring与yml集成思路的分析

    在这里插入图片描述

        1. 准备yml配置文件
         init.yml
         name:suns
         proword:123456
         2. 读取yml  转换成Properties
          YamlPropertiesFactoryBean.setResources( yml配置文件的路径) new ClassPathResource();
          YamlPropertiesFactoryBean.getObject()---->Properties
          3. 应用PropertySourcesPlaceholderConfigure
          PropertySourcesPlaceholderConfigure.setProperties();
          4. 类中 @Value注解  注入 
    
  3. Spring与YML集成编码

  • 环境搭建

        <dependency>
          <groupId>org.yaml</groupId>
          <artifactId>snakeyaml</artifactId>
          <version>1.26</version>
      </dependency>
      最低版本1.18
    
  • 编码

    1. 准备yml配置文件
    

在这里插入图片描述

  2. 配置Bean中操作  完成yaml读取与 PropertySourceplaceholderConfigure的创建
package com.baizhiedu.yml;

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import java.util.Properties;

@Component
@ComponentScan(basePackages="com.baizhiedu.yml")
public class YmlAutoConfiguration{


    @Bean
    public PropertySourcesPlaceholderConfigurer configurer(){


        YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
        yamlPropertiesFactoryBean.setResources(new ClassPathResource("init.yml"));
        Properties properties = yamlPropertiesFactoryBean.getObject();


        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
    configurer.setProperties(properties);
    return configurer;

    }
}







 /**
     * 用于测试Yml
     */
    @Test
    public void test3(){
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(YmlAutoConfiguration.class);
    Account account = (Account)ctx.getBean("account");
    System.out.println("account.getname"+account.getName());
    System.out.println("account.getPassword()"+account.getPassword());


    }
   3. 类  加入@Value注解

在这里插入图片描述
6. Spring 与YMl集合处理的问题

 1. 集合处理的问题
   
      因为使用YamlPropertiesFactoryBean解析yml文件,但是它解析不了list类型的数据
      所以yml中list赋值时采用
      list: 111,222
      而不是采用传统的
      list: 
       - 1111
       - 2222
       
       实体类中的注解
       Spring采用El表达式解决
       采用   @Value("#{'${list}'.split(',')}")
       
       不用传统的@Value("${list}")
          
           
        2. 对象类型的YAMl进行配置时 过于繁琐
        @Value("${account.name}")
         
         SpringBoot  @ConfigurationProperties
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值