Spring学习笔记

Spring

框架概述

  1. Spring是轻量级的JavaEE框架
  2. Spring可以解决企业应用开发的复杂性
  3. Spring有两个核心部分:IOC和AOP
    1. IOC:控制反转,把创建对象过程交给Spring容器进行管理
    2. AOP:面向切面编程,在不修改源代码的基础上进行功能加强
  4. Spring特点
    1. 方便解耦,简化开发
    2. AOP编程支持
    3. 方便程序测试
    4. 方便和其它框架进行整合
    5. 方便进行事物操作
    6. 降低API开发难度

IOC容器

  1. 什么是IOC:

​ 控制反转:把对象创建和对象之间的关系交给Spring容器进行管理

  1. 使用IOC的目的:

​ 降低耦合度

IOC底层原理

  1. xml解析、工厂模式、反射

  2. IOC过程

    1. 配置xml文件,配置创建的对象

      <bean id="user" class="com.jiuheng.UserMapper" ></bean> 
      
    2. 创建工厂类获取对象

      class UserFactory{
          public static UserMapper getUserMapper(){
              String classCalue = class属性值; // 1.解析xml文件
              Class clazz = Class.forName(classValue); //2.通过反射创建对象
              return (UserMapper)clazz.newInstace(); //返回对象
          }
      }
      

IOC接口

  1. IOC思想是基于IOC容器完成,IOC容器底层是对象工厂

  2. Spring提供IOC容器两种实现方式(两个接口):

    1. BeanFactory:IOC容器基本实现,是Spring内部的使用接口,一般不提供开发人员进行使用

      特点:加载xml配置文件时不会创建对象,在获取对象时才会创建对象

      1. ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用

        特点:在加载XML配置文件时就会把配置文件中的对象创建出来

IOC操作–Bean管理

什么是Bean管理

Bean管理指的是两个操作:

1. Spring创建对象
2. Spring注入属性

Bean管理操作的两种方式:

  1. 基于XML配置文件方式
  2. 基于注解方式
Bean管理(基于XML文件方式)
  1. 基于xml方式创建对象

    1. 在Spring配置文件中使用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">
      
          <bean id="user" class="com.jiuheng.entity.User" />
      </beans>
      
    2. bean标签中常见的属性:

      1. id属性:对象的唯一标识
      2. class属性:类的全路径
    3. 创建对象时默认是执行无参构造完成对象的创建

  2. 基于XML方式注入属性:

    1. DI(依赖注入):就是注入属性

      1. 使用set方法注入

        1. 创建对象,对象属性及对象属性所对应的get,set方法

          package com.jiuheng.entity;
          
          /**
           * @ClassName User
           * @Description user
           * @Author 程茂强
           * @Data 2022/10/5 15:18
           * @Version 1.0
           */
          public class User {
          
              private String name;
              private Integer age;
          
              public User() {
              }
          
              public User(String name, Integer age) {
                  this.name = name;
                  this.age = age;
              }
          
              public String getName() {
                  return name;
              }
          
              public void setName(String name) {
                  this.name = name;
              }
          
              public Integer getAge() {
                  return age;
              }
          
              public void setAge(Integer age) {
                  this.age = age;
              }
          
              @Override
              public String toString() {
                  return "User{" +
                          "name='" + name + '\'' +
                          ", age=" + age +
                          '}';
              }
          }
          
          
        2. 在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">
          
          <!--    set注入属性-->
              <bean id="user" class="com.jiuheng.entity.User" >
          
          <!--     使用property标签完成属性注入
                   name: 类中的属性名称
                   value:向属性中注入的值
          
              -->
                  <property name="name" value="程茂强"/>
                  <property name="age" value="19"/>
              </bean>
          
          </beans>
          
      2. 使用构造方法注入

        1. 创建对象,对象属性及构造方法

        2. 在Spring配置文件中配置对象创建,配置构造注入

          <!--  有参构造注入属性  -->
              <bean id="student" class="com.jiuheng.entity.Student">
          <!--
                  使用constructor-arg标签完成属性注入
                  name: 类中的属性名称
                   value:向属性中注入的值
          -->
                  <constructor-arg name="name" value="程茂强" ></constructor-arg>
                  <constructor-arg name="age" value="19"></constructor-arg>
              </bean>
          
Xml注入其它类型属性
  1. 注入null属性值包含特殊字符

    1. 注入null值

      <property name="name">
         <null/> <!--向name属性中注入空值-->
      </property> 
      
    2. 属性值中包含特殊字符(把特殊字符写入到CDATA中)

      <property name="name">
          <value><![CDATA[<<程茂强>>]]></value>
      </property>
      
  2. 外部Bean的注入

    举例:

    1. 创建service类和mapper类

    2. 在service中调用mapper中的方法

      public class UserService {
      
          private UserMapper userMapper;
      
          public UserMapper getUserMapper() {
              return userMapper;
          }
      
          public void setUserMapper(UserMapper userMapper) {
              this.userMapper = userMapper;
          }
      
          public void add(){
              System.out.println("useService add ............");
              userMapper.update();
          }
      }
      
    3. 在spring文件中进行配置

      <bean id="userService" class="com.jiuheng.service.UserService">
          <property name="userMapper" ref="userMapper"></property>
      </bean>
      <bean id="userMapper" class="com.jiuheng.mapper.impl.UserMapperImpl"></bean>
      
  3. 注入属性–内部bean和级联赋值

    当对象中的属性类型为其它对象时可以使用

    <bean id="student" class="com.jiuheng.entity.Student">
        <constructor-arg name="name" value="程茂强" ></constructor-arg>
        <constructor-arg name="age" value="19"></constructor-arg>
        <property name="user">
            <bean id="user" class="com.jiuheng.entity.User">
                <property name="name" value="程茂强"/>
                <property name="age" value="19"/>
            </bean>
        </property>
    </bean>
    
  4. 注入数组类型属性、注入List类型属性、注入Map类型属性

    	<bean id="book" class="com.jiuheng.entity.Book">
            <property name="author">
                <array>
                    <value>张三1</value>
                    <value>张三2</value>
                    <value>张三3</value>
                </array>
            </property>
            <property name="list">
                <list>
                    <value>张三1</value>
                    <value>张三2</value>
                    <value>张三3</value>
                </list>
            </property>
            <property name="map">
                <map>
                    <entry key="Java" value="spring"/>
                    <entry key="sql" value="mysql"/>
                </map>
            </property>
        </bean>
    
FactoryBean

Spring中有两种Bean类型,一种时普通的bean,另一种是工厂Bean(FactiryBean)

  1. 普通Bean

    在xml配置文件种定义的Bean类型就是返回的类型

  2. 工厂Bean

    在xml配置文件种定义的Bean类型可以和返回类型不一样

    实现FactoryBean接口,实现接口中的方法

Bean的作用域

Spring默认对象是单实例对象(获取到的对象都是同一对象)

可以通过Spring配置文件中的bean标签的scope属性进行设置

scope属性值:

​ singleton:单实例

​ prototype:多实例

singleton和prototype的区别:

  1. singleton:单实例,prototype:多实例

  2. 设置scope值为singleton时,加载spring配置文件时就会创建单实例对象

    设置scope值为prototype时,加载spring配置文件时不会创建实例对象,只有在getBean方法执行时才会创建多实例对象。

Bean的生命周期
  1. 通过构造器或工厂方法创建Bean实例
  2. 为Bean的属性设置值和对其它Bean的引用
  3. 调用Bean的初始化方法(需要自己配置)
  4. 正常使用Bean
  5. 当容器关闭时调用Bean的销毁方法(需要自己配置)

在Spring配置文件中的bean标签中有init-method属性配置初始化方法

destory-method属性配置销毁方法

Bean的后置处理器

bean 后置处理器允许在调用初始化方法前后对 bean 进行额外的处理

bean 后置处理器使用时需要实现接口:

org.springframework.beans.factory.config.BeanPostProcessor

在初始化方法被调用前后,Spring 将把每个 bean 实例分别传递给上述接口的以下两个方法:

postProcessBeforeInitialization(Object, String)调用前

postProcessAfterInitialization(Object, String)调用后

如果bean实例为单例那在容器运行时就会执行后置处理器方法和初始化方法,在容器销毁时又会执行销毁方法

总结一下后置处理器的执行过程

  1. 通过构造器或工厂方法创建 bean 实例

  2. 为 bean 的属性设置值和对其他 bean 的引用

  3. 将 bean 实例传递给 bean 后置处理器的postProcessBeforeInitialization()方法

  4. 调用 bean 的初始化方法

  5. 将 bean 实例传递给 bean 后置处理器的postProcessAfterInitialization()方法

  6. bean 可以使用了

  7. 当容器关闭时调用 bean 的销毁方法

Bean管理(基于注解方式)

Spring针对Bean管理中创建对象提供四个注解

  1. @Component
  2. @Service
  3. @Controller
  4. @Respository

属性注入Spring提供了以下注解

  1. AutoWired:根据属性类型进行自动注入

  2. @Qualifier:根据属性名称进行自动注入

  3. @Resource:可以根据类型也可以根据名称自动注入

  4. @Value:注入普通类型属性(字符串等)

AOP

AOP:面向切面编程

​ 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分之间的耦合度降低,提高程序的可重用性,同时提高开发效率。

通俗来讲:在不修改源代码的基础上,在主干功能里添加新功能。

底层原理

AOP的底层原理:动态代理

有接口情况–使用JDK动态代理

创建接口实现类的代理对象,增强类的方法

无接口的情况–使用CGLIB动态代理

创建当前类的子类代理对象,增强类的方法

AOP术语

  1. 连接点

    可以被增强的方法被称为连接点

  2. 切入点

    实际被增强的方法

  3. 通知

    实际增加的代码逻辑部分

  4. 切面

    把通知应用到切入点的过程

通知的类型

  1. 前置通知(Before):在目标方法被调用之前调用通知功能
  2. 后置通知(After):在目标方法完成之后调用通知,此时不关心方法的输出结果是什么
  3. 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为
  4. 异常通知(After-throwing):在目标方法抛出异常后调用通知
  5. 返回通知(After-returning):在目标方法成功执行之后调用通知

切入点表达式

作用:知道哪个类的哪个方法进行了增强

语法结构:

execution([权限修饰符] [返回值类型] [类的全限定名].[方法名] ([参数列表]) [异常类型])

其中权限修饰符和异常类型可以省略。

切入点通配符

* :单个独立的任意符号

… :多个连续的任意符号

  • 返回值类型: * 表示任意返回值类型

  • 方法名:* 表示所有方法

  • 参数名:(…) 表示任意参数

    ​ (*) 表示任意一个参数

    ​ (*,*) 表示任意两个参数

切入点表达式例子

//指定切入点为项目中任意类的任意方法

execution(* *…*(…))

//指定切入点为com.jiuheng包下的所有方法

execution(* com.jiuheng.*.*(…))

//指定切入点为service层的所有方法

execution(* com.jiuheng.service.*.*(…))

//指定切入点为service层的save开头的方法

execution(* com.bighorn.service.*.save*(…))

//指定切入点为所有xxxService业务层接口的所有方法

execution(* com.jiuheng.*.*Service.*(…)) *

*//指定切入点为所有xxxService业务层接口的select开头的方法

execution( com.jiuheng.*.*Service.select*(…))

AspectJ注解操作AOP

  1. 在Spring配置文件加@EnableAspectJAutoProxy(proxyTargetClass = true)开启自动代理功能

  2. 添加切面

    package com.jiuheng.log;
    
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    
    /**
     * @ClassName Log
     * @Description 日志
     * @Author 程茂强
     * @Data 2022/10/6 13:42
     * @Version 1.0
     */
    @Aspect
    @Component
    public class Log {
    
        @Before("execution(* com.jiuheng.*.*.*.*(..))")
        public void before(){
            System.out.println("before执行");
        }
    
        @After("execution(* com.jiuheng.*.*.*.*(..))")
        public void after(){
            System.out.println("after执行");
        }
    
        @AfterReturning("execution(* com.jiuheng.*.*.*.*(..))")
        public void after_returning(){
            System.out.println("AfterReturning执行");
        }
    }
    

    当切入点相同时可以使用@Pointcut注解抽取

    package com.jiuheng.log;
    
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    
    /**
     * @ClassName Log
     * @Description 日志
     * @Author 程茂强
     * @Data 2022/10/6 13:42
     * @Version 1.0
     */
    @Aspect
    @Component
    public class Log {
        
        @Pointcut("execution(* com.jiuheng.*.*.*.*(..))")
        public void pointCut(){
            
        }
    
        @Before("pointCut()")
        public void before(){
            System.out.println("before执行");
        }
    
        @After("pointCut()")
        public void after(){
            System.out.println("after执行");
        }
    
        @AfterReturning("execution(* com.jiuheng.*.*.*.*(..))")
        public void after_returning(){
            System.out.println("AfterReturning执行");
        }
    
    }
    
    

    当有多个增强类对同一方法进行增强时可以在增强类上添加@Order(int)注解,int值越小优先级越高

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值