Spring学习(一)

简介&使用及学习

Spring现在包含着Spring boot、Spring Cloud等一系列技术,但是作为Spring的初学者,我们需要学习Spring Framework,这是Spring最初的设计框架,所以以下先用Spring代替Spring Framework。

Spring Framework主要包括几个模块:

  • 支持IoC和AOP的容器;
  • 支持JDBC和ORM的数据访问模块;
  • 支持声明式事务的模块;
  • 支持基于Servlet的MVC开发;
  • 支持基于Reactive的Web开发;
  • 以及集成JMS、JavaMail、JMX、缓存等其他模块。

Spring(Spring Framework)主要就包括IoC和AOP两个方面。

Spring最初是以写配置的方式来开发,然后出现了注解功能,我们在日常开发中通常是使用写注解的方式。但是注解实际上是写配置的方式的变形,所以我们想要了解原理,仍然要学习如何写配置。

系统架构

  • 最底层是一个核心容器
  • 然后是AOP和Aspects
  • 然后是数据访问(包含一个高效的事务控制)
  • 然后是Web开发

核心容器

思想:

核心概念:IoC、DI

解决的问题:

  • 代码耦合度偏高(当修改一个功能时需要重新使用一个对象,于是跟此对象关联的所有地方都要进行修改)

解决方案:

  • 不主动产生对象,转为由外部提供对象

技术方案:

  • IoC(控制反转)

IoC就是一个产生对象的容器,IoC负责管理大量的对象的创建和初始化,被创建或被管理的对象在容器中统称为Bean

若IoC中的对象存在依赖关系,可以直接在容器中进行绑定,这就是DI(依赖注入)技术

如何实现:

IoC的实现
  1. 首先确定自己需要管理的类
  2. 在resources中创建Spring配置文件
  3. 编写配置 <bean id="" class="" ...></bean>
  4. 获取IoC容器ApplicationContext ctx = new ClassPathXmlApplicationContext(创建的配置文件)
  5. 获取Bean ctx.getBean 方法
DI的实现
  1. 创建其他对象不再使用new方法

  2. 创建一个set方法

  3. 在配置文件中添加依赖配置

    <property name="属性中的名称" ref="其他bean的名称"/>

Bean的配置

bean的基础属性有id、class,也可以使用name为bean添加别名;

默认创建的bean是单例,可以在配置中添加scope=”prototype”设置为非单例,可以复用的对象都可以以单例形式交给IoC管理。

bean是如何创建的

本质上bean也是用类的构造方法来创建bean的,但是是使用java的反射机制实行的(private构造方法也可以创建),默认是使用无参构造方法实现的,需要提供无参构造方法。

bean也有其他方式实例化,比如使用静态工厂的方式。在使用静态工厂的方式创建对象时,需要在配置中将类改为工厂类名,然后通用再加一个factory-method="" 来实现。

还有使用实例工厂的方式,这种还需要再实例化这个工厂,比较复杂。配置时要先把工厂的bean配置出来,然后配置要使用的bean的factory-method和factory-bean。

后来Spring改进了实例工厂的方式,需要接口FactoryBean,这种方式在配置时就不用配置完工厂bean后再配置要使用的bean,只需要配置工厂bean。这种方法可以在工厂类中使用isSingleto()方法修改是否是单例。

bean的生命周期

在配置中使用init-method=”” destoy-method=”” 配置bean的生命周期,在类中写init和destroy方法。(或者使用接口的方式)

关闭容器的方式(方法是ClassPathXmlApplication类中的方法,需要创建此类型的IoC容器)

  • close
  • registerShutdownHook()
依赖注入的实现
  1. 使用set方法,然后配置<porperty name="" ref=""/>

    如果是基本数据类型或者String则property中的ref换成valuie即可

  2. 构造器注入。将构造方法改成带参数的构造方法,配置中使用 <constructor name="形参名" ref/value=""/> 配置,name=""可以换成index和type索引属性。

  3. 依赖的自动装配。 在bean的配置中加上 autowire="" 可完成自动装配,需要注意的是类中的set方法不可省去,但是省去了写 property这一行。关于参数byType指按类型装配,一个类只能有一个对象/bean,这种情况需要使用参数byName,Name是对象名,一般是使用byType。自动装配只能应用于引用类型,不能应用于基本类型。自动装配的优先级低于手动装配。

  4. 集合注入

    • 数组:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      <property name="">
      <array>
      <value>1</value>
      <value>2</value>
      <value>3</value>
      <ref bean=""/>
      ...
      </array>
      </property>
    • list:

      1
      2
      3
      4
      5
      6
      7
      8
      <property name="">
      <list>
      <value>1</value>
      <value>2</value>
      <value>3</value>
      ...
      </list>
      </property>
    • set:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      <property name="">
      <set>
      <value>1</value>
      <value>2</value>
      <value>3</value>
      <!--set中重复的部分会过滤掉-->
      ...
      </set>
      </property>
    • map

      1
      2
      3
      4
      5
      6
      7
      <property name="">
      <map>
      <entry key="one" value="1"/>
      <entry key="two" value="2"/>
      ...
      </map>
      </property>
    • props(properties)

      1
      2
      3
      4
      5
      6
      7
      8
      <property name="">
      <props>
      <prop key="one">1</prop>
      <prop key="two">2</prop>
      <prop key="three">3</prop>
      ...
      </props>
      </property>
加载其他的properties文件
  1. 开启context命名空间
  2. 使用context命名空间加载指定properties文件
  3. 使用${ }读取加载的属性值

容器补充

  • 从文件系统加载配置文件

    1
    ApplicationContext ctx = new FileSystemXmlApplicationContext("path/to/.xml")
  • 加载多个配置文件

    1
    ApplicationContext ctx = new ClassPathXmlApplicationContext("name1.xml","name2.xml")
  • 获取bean的方式补充

    1
    2
    3
    BookDao bookDao = (BookDao) ctx.getBean("bookDao")//根据名称
    BookDao bookDao = ctx.getBean("bookDao",BookDao.class)//根据名称并指定类
    BookDao bookDao = ctx.getBean(BookDao.class)//根据类

半注解开发

半注解开发是Spring2的时候推出的开发模式,在Spring3后出现了纯注解开发的模式。具体实现如下:

  1. 在要配置的bean前加上@Component注解,
  2. 在配置文件中通过组件扫描加载bean
  3. @Service用于业务层的bean @Repository用于数据层的bean @Controller用于表现层的bean

纯注解开发

创建IoC容器和bean

  1. 新建一个配置类,使用此配置类替代xml配置文件,加上注解@Configuration(代替注解的说明)和@ComponentScan(Bean模块) (代替组件扫描)

  2. 初始化容器的语句不再是

    1
    ApplicationContext ctx = new ClassPathXmlApplicationContext("name.xml")

    而是

    1
    ApplicationContext ctx = new AnnotationConfigApplicationContext(配置类的名称.class)

配置bean

  • 修改非单例:加注解 @Scope("prototype")
  • 设置初始化和销毁方法:@PostConstruct @PreDestroy
  • 自动装配实现依赖注入 @Autowired ,并且此时不用再创建set方法实现注入了。
  • 想要按名称注入就需要在@Autowired 后加上 @Qualifier("name")
  • 注入基本类型和String类型 加注解 @Value("值")

加载外部配置文件

  1. 在配置类中加上标签 @PropertySource("name.properties")
  2. 注入时使用${外部配置文件中的变量名}

第三方bean管理

  1. 在配置类中新建一个方法获得想要的bean
  2. 加上@Bean注解
  3. 一般的要把这个方法写在新的配置类中,然后在主配置类中加上注解 @import() 或者 @ComponentScan()

想要在第三方bean中进行依赖注入,如果是简单类型使用@Value注解,如果是引用类型的bean直接在获取bean的方法加上形参即可。

AOP面向切面编程

在不修改原始设计的基础上进行功能增强,符合Spring无侵入式设计理念。

常用名词:
  • 连接点:程序执行过程中的任意位置
  • 切入点:匹配连接点的式子
  • 通知:在切入点进行的操作
  • 通知类:定义通知的类
  • 切面:描述通知和切入点的对应关系
实现思路:
  1. 导入坐标(pom.xml)

  2. 制作连接点方法

  3. 制作共性功能

  4. 定义切入点

    加上@Pointcut(“切入点表达式”)注解

  5. 绑定切入点和通知的关系

    加上在何处执行共性方法的注解,如@Before(“切入点”)

在通知类前加上@Component和@Aspect注解,然后在配置类前加上@EnableAspectJAutoProxy注解,即启动切面编程。

切入点表达式

标准格式:

动作关键字 (访问修饰符 返回值 包名.类/接口.方法名(参数) 异常名)

在AOP切入点表达式中可以使用通配符

  • *: 单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀出现
  • ..: 多个连续的任意符号,可以独立出现,常用于简化包名和参数的书写
  • +: 专用于匹配子类类型
AOP通知类型
  • 前置通知:@Before("pt()")

  • 后置通知:@After("pt()")

  • 环绕通知:@Around("pt()"),通知上要有pjp.proceed();表示对原方法的调用,并且通知方法需要有返回值。

    标准写法如下:

    1
    2
    3
    4
    5
    6
    7
    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp) throws Throwables{
    原始方法前想要执行的代码
    Object ret = pjp.proceed();//表示调用了原始方法
    原始方法后想要执行的代码
    return ret;
    }
  • 无异常运行完成后:@AfterReturning("pt()")

  • 抛出异常后:@AfterThrowing("pt()")

AOP通知获取数据
  • 获取切入点方法的参数
    1. JointPoint:适用于前置、后置、返回后、抛出异常后通知
    2. ProceedJointPoint:适用于环绕通知
  • 获取切入点方法返回值
    1. 返回后通知
    2. 环绕通知
  • 获取切入点方法运行异常信息
    1. 抛出异常后通知
    2. 环绕通知

Spring学习(一)
https://rainzz.cn/2025/03/14/Spring学习1/
作者
rainzz
发布于
2025年3月14日
许可协议