Spring 相关面试题

一. Spring 简介

1.1 Spring 简介

  • Spring 是一个为简化企业级开发而生的开源框架
  • Spring 是一个 IOC(DI)AOP容器框架
  • IOC全称:Inversion of Control【控制反转】
    • 将对象【万物皆对象】控制权交给Spring
  • DI全称:(Dependency Injection):依赖注入
  • AOP 全称:Aspect-Oriented Programming,面向切面编程

1.2 搭建 Spring 框架步骤

  • 导入jar包

  •  编写核心配置文件
    • 配置名称:applicationContext.xml【beans.xml 或 spring.xml】

  • 使用核心类库

1.3 Spring 特性

  • 非侵入式:基于 Spring 开发的应用中的对象可以不依赖于 Spring 的 API
  • 容器:Spring 是一个容器,因为它包含并且管理应用对象的生命周期
  • 组件化:Spring 实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和java注解组合这些对象。
  • 一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring自身也提供了表述层的SpringMVC和持久层的JDBCTemplate)

1.4 Spring 中 getBean() 三种方式

  • getBean(String beanId):通过beanId获取对象
    • 不足:需要强制类型转换,不灵活
  • getBean(Class clazz):通过 Class 方式获取对象
    • 不足:容器中有多个相同类型 bean 的时候,会报如下错误:
      • expected single matching bean but found 2: stuZhengzhong,stuZhouxu
  • getBean(String beanId,Clazz clazz):通过 beanId 和 Class 获取对象
    • 推荐使用(三种方式如下图)

 通过 Spring 创建对象,都是调用的无参构造器

注意:框架默认都是通过无参构造器,帮助我们创建对象。

所以:如提供对象的构造器时,一定添加无参构造器

1.5 bean 标签详解

  • 属性:
    • id:bean 的唯一标识
    • class:定义bean的类型【class 全类名】
  • 子标签
    • property:为对象中属性赋值【set 注入】
      • name 属性:设置属性名称
      • value属性:设置属性数值

二.SpringIOC 底层实现

IOC:将对象的控制权反转给 Spring

2.1 BeanFactory 与 ApplicationContext

  •  BeanFactory:IOC 容器的基本实现,是Spring 内部的使用接口,是面向Spring本身的,不是提供给开发人员使用的。
  • ApplicationContext:BeanFactory 的子接口,提供了更多高级特性。面向Spring的使用者,几乎所有场合都使用 ApplicationContext 而不是底层的 BeanFactory。

2.2 图解 IOC 类的结构

 结构:

  •  BeanFactory:Spring 底层 IOC 实现【面向 Spring 框架】
    • ...
      • ApplicationContext:面向程序员
        • ConfigurableApplicationContext:提供关闭或刷新容器对象方法
          • ...
            • ClassPathXmlApplicationContext:基于类路径检索 xml 文件
            • AnnotationConfigApplicationContext:基于注解创建容器对象
            • FileSystemXmlApplicationContext:基于文件系统检索 xml 文件

三.Spring 依赖注入数值问题【重点】

3.1 字面量数值

  • 数据类型:基本数据类型及包装类,String
  • 语法:value属性或value标签

3.2 CDATA区

  • 语法:<![CDATA[]]>
  • 作用:在 xml 中定义特殊字符时,使用 CDATA 区

如:

 在 Mybatis 的 sql 语句中有特殊符号,也可以用

3.3 外部已声明bean及级联属性赋值

  • 语法:ref
  • 注意:级联属性更改数值会影响外部声明 bean【ref 赋值的是引用】
  • 示例代码:

 

3.4 内部bean

  • 概述
    • 内部类:在一个类中完整定义另一个类,当前类称之为内部类
    • 内部bean:在一个bean中完整定义另一个bean,当前bean称之为内部bean
  • 注意:内部bean不会直接装配到IOC容器中
  • 示例代码:

3.5 集合

  • List 

  •  Map 

 提取map

第四章 Spring 依赖注入方式【基于xml】

为属性赋值方式

  • 通过 xxxset()方法
  • 通过构造器
  • 反射

4.1 set注入

  • 语法:<property>

4.2 构造器注入

  • 语法:<constructor-arg>

 4.3 p名称空间注入

导入名称空间:xmlns:p="http://www.springframework.org/schema/p"

  • 语法:<bean p:xxx>

 第五章 Spring 管理第三方bean

5.1 Spring 管理 druid 步骤

  • 导入 jar 包
  • 编写db.properties配置文件
  • 编写applicationContext.xml相关代码

 第六章 Spring 中 FactoryBean

 6.1 Spring中两种bean

  •  一种是普通bean
  • 另一种是工厂bean【FactoryBean】
    • 作用:如果需要我们程序员参与到bean的创建时,使用FactoryBean

6.2 FactoryBean 使用步骤

  • 实现FactoryBean接口
  • 重写方法【三个】① getObject ② getObjectType ③ isSingleton
  • 装配工厂bean
  • 测试
package com.yzj.backend.factory;

public class MyFactoryBean implements FactoryBean<Dept> {

    /**
     * getObject():参与对象创建的方法
     * @return
     * @throws Exception
     */
    @Override
    public Dept getObject() throws Exception {
        Dept dept = new Dept(101,"研发部门");
        return dept;
    }

    /**
     * 设置参与对象class
     * @return
     */
    @Override
    public Class<?> getObjectType() {
        return Dept.class;
    }

    /**
     * 设置当前对象是否为单例
     * @return
     */
    @Override
    public boolean isSingleton() {
        return true;
    }
}

第七章 Spring 中 bean 的作用域

7.1 语法

  • 在bean标签中添加属性:scope属性即可

7.2 四个作用域

  • singleton【默认值】:单例【在容器中只有一个对象】
    • 对象创建时机:创建容器对象时,spring创建我们的对象【无参构造器】
  • prototype:多例【在容器中有多个对象】
    • 对象创建时机:getBean()方法被调用时,创建对象执行
  • request:请求域
    • 当前请求有效,离开请求域失效
    • 当前请求:URL不变即为当前请求
  • session:会话域
    • 当前会话有效,离开当前会话失效
    • 当前会话:当前浏览器不关闭不更换即为当前会话

第八章 Spring中bean的生命周期

8.1 bean的生命周期

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

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

postProcessBeforeInitialization(Object,String):在bean的初始化之前执行

③ 调用bean的初始化方法

postProcessAfterInitialization(Object,String):在bean的初始化之后执行

④ bean可以使用了

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

8.2 bean的后置处理器

  • 作用:在调用初始化方法前后对bean进行额外的处理。
  • 实现:
    • 实现BeanPostProcessor接口
    • 重写方法
      • postProcessBeforeInitialization(Object,String):在bean的初始化之前执行
      • postProcessAfterInitialization(Object,String):在bean的初始化之后执行
    • 在容器中装配后置处理器
  • 注意:装配后置处理器会为 当前容器中每个bean 均装配,不能为局部bean装配后置处理器

第九章 Spring 中自动装配【基于XML】

9.1 Spring 中提供两种装配方式

  • 手动装配
  • 自动装配

9.2 Spring 自动装配语法及规则

  • 在bean标签中添加属性:Autowire即可
    • byName:对象中属性名称与容器中的beanId进行匹配,如果属性名与beanId数值一致,则自动装配成功
    • byType:对象中属性类型与容器中class进行匹配,如果唯一匹配则自动装配成功
      • 匹配 0 个:未装配
      • 匹配多个,会报如下错
        • expected single matching bean but found 2: deptDao,deptDao2
  • 注意:基于XML方式的自动装配,只能装配非字面量数值

9.3 总结

  • 基于XML自动装配,底层使用set注入
  • 最终:不建议使用 byName,byType,建议使用注解方式自动装配

第十章 Spring 中注解【非常重要】

10.1 使用注解将对象装配到 IOC 容器中

约定:约束 > 配置【注解 > XML】> 代码

位置:在类上面标识

注意:

  • Spring 本身不区分四个注解【四个注解本质是一样的@Component】,提供四个注解的目的只有一个:提高代码的可读性
  • 使用注解装配对象,默认将类名首字母小写作为beanId
  • 可以使用value属性,设置beanId;当注解中只使用一个value属性时,value关键字可省略
  • 装配对象四个注解
    • @Component:装配普通组件到IOC容器
    • @Repository:装配持久化层组件到IOC容器
    • @Service:装配业务逻辑层组件到IOC容器
    • @Controller:装配控制层 | 表示层组件到IOC容器
  • 使用注解步骤
    • 导入相关jar包【已导入】
    • 开启组件扫描
    • 使用注解标识组件 

10.2 使用注解装配对象中属性【自动装配】

  • @Autowired注解
    • 作用:自动装配对象中属性
    • 装配原理:反射机制
    • 装配方式
      • 先按照byType进行匹配
        • 匹配 1 个:匹配成功,正常使用
        • 匹配 0 个:
          • 默认【@Autowired(required=true)】报错
          • @Autowired(required=false),不会报错
        • 匹配多个
          • 再按照byName进行唯一筛选
            • 筛选成功【对象中属性名称 == beanId】,正常使用
            • 筛选失败【对象中属性名称 != beanId】,报如下错误:
              //expected single matching bean but found 2: deptDao,deptDao2
    • @Autowired中required属性
      • true:表示被标识的属性必须装配数值,如未装配,会报错
      • false:表示被标识的属性不必须装配数值,如未装配,不会报错。
  • @Qualifier注解
    • 作用:配合@Autowired一起使用,将设置beanId名称装配到对象属性中
    • 注意:不能单独使用,需要与@Autowired一起使用
  • @Value
    • 作用:装配对象中属性【字面量数值】

第十一章 Spring 中组件扫描

11.1 默认使用情况

 11.2 包含扫描

  • 注意:
    • 使用包含扫描之前,必须设置 use-default-filters="false"【关闭当前包及其子包的扫描】
    • type
      • annotation:设置被扫描注解的全类名
      • assignable:设置被扫描实现类的全类名

 11.3 排除扫描

 第十三章 Spring 完全注解开发【0配置】

13.1 完全注解开发步骤

1.创建配置类

2.在class上面添加注解

  • @Configuration:标识当前类是一个配置类,作用:代替XML配置文件
  • @ComponentScan:设置组件扫描当前包及其子包

3.使用AnnotationConfigApplicationContext容器对象

13.2 实例代码

 

第十四章 Spring 集成 Junit4

14.1 集成步骤

1.导入jar包

  • spring-test-5.3.1.jar

2.指定Spring的配置文件的路径

  • 【@ContextConfiguration】

3.指定Spring环境下运行Junit4的运行器

  • @RunWith

 第十五章 AOP前奏

15.1 代理模式

  • 代理模式:我们需要做一件事情,又不期望自己亲力亲为,此时,可以找一个代理【中介】
  • 我们【目标对象】与中介【代理对象】不能相互转换,因为是“兄弟”关系

 15.2 为什么需要代理【程序中】

  • 需求:实现【加减乘除】计算器类
    • 在加减乘除方法中,添加日志功能【在计算之前,记录日志。在计算之后,显示结果。】
  • 实现后发现问题如下
    • 日志代码比较分散,可以提取日志类
    • 日志代码比较混乱,日志代码【非核心业务代码】与加减乘除方法【核心业务代码】书写一处
  • 总结:在核心业务代码中,需要添加日志功能,但不期望在核心业务代码中书写日志代码
    • 此时:使用代码模块解决问题【先将日志代码横向提取到日志类中,再动态织入回到业务代码中】

15.3 手动实现动态代理环境搭建

  • 实现方式
    • 基于接口实现动态代理:JDK动态代理
    • 基于继承实现动态代理:Cglib,Javassist动态代理
  • 实现动态代理关键步骤
    • 一个类:Proxy
      • 概述:Proxy代理类的基类【类似Object】
      • 作用:newProxyInstance():创建代理对象
    • 一个接口:InvocationHandler
      • 概述:实现【动态织入效果】关键接口
      • 作用:invoke(),执行invoke()实现动态织入效果

15.4 手动实现动态代理关键步骤

注意:代理对象与实现类【目标对象】是"兄弟"关系,不能相互转换

  • 创建类【为了实现创建代理对象工具类】
  • 提供属性【目标对象:实现类】
  • 提供方法【创建代理对象】
  • 提供有参构造器【避免目标对为空】

工具类

package com.yzj.backend.aop;

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

public class MyProxy {

    /**
     * 目标对象【目标客户】
     */
    private Object target;

    public MyProxy(Object target){
        this.target = target;
    }

    /**
     * 获取目标对象的,代理对象
     * @return
     */
    public Object getProxyObject(){
        Object proxyObj = null;

        /**
         * 类加载器【ClassLoader loader】,目标对象类加载器
         * 目标对象实现接口:Class<?>[] interfaces,目标对象实现所有接口
         * InvocationHandler h
         */
        ClassLoader classLoader = target.getClass().getClassLoader();
        Class<?>[] interfaces = target.getClass().getInterfaces();
        //创建代理对象
        proxyObj = Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
            //执行invoke()实现动态织入效果
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //获取方法名【目标对象】
                String methodName = method.getName();
                //执行目标方法之前,添加日志
                MyLogging.beforeMethod(methodName, args);
                //触发目标对象目标方法
                Object rs = method.invoke(target, args);
                //执行目标方法之后,添加日志
                MyLogging.afterMethod(methodName, args);
                return rs;
            }
        });
        return proxyObj;
    }
}

测试

 

第十六章 Spring中AOP

16.1 AspectJ框架【AOP框架】

  • AspectJ是java社区里最完整最流行的AOP框架。
  • 在Spring2.0以上版本中,可以使用基于AspectJ注解或基于XML配置的AOP。

16.2 使用AspectJ步骤

1.添加jar包支持

2.配置文件

  • 开启组件扫描
  • 开启AspectJ注解支持

3.将MyLogging类上面添加注解

  • @Component:将当前类标识为一个组件
  • @Aspect:将当前类标识为切面类【非核心业务提取类】

4.将MyLogging中的方法中添加通知注解

  • @Before

5.测试

 16.3 Spring 中 AOP 概述

  • AOP:Aspect-Oriented Programming,面向切面编程【面向对象的一种补充】
    • 优势:
      • 解决代码分散问题
      • 解决代码混乱问题
  • OOP:Object-Oriented Programming,面向对象编程

16.4 Spring中AOP相关术语

  1. 横切关注点:非核心业务代码【日志】,称之为横切关注点
  2. 切面(Aspect):将横切关注点提取到类中,这个类称之为切面类
  3. 通知(Advice):将横切关注点提取到类中之后,横切关注点改名为:通知
  4. 目标(Target):目标对象,指的是需要被代理的对象【实现类】
  5. 代理(Proxy):代理对象可以理解为:中介
  6. 连接点(Joinpoint):通知方法需要指定通知位置,这个位置称之为:连接点【通知之前】
  7. 切入点(pointcut):通知方法需要指定通知位置,这个位置称之为:切入点【通知之后】

第十七章 AspectJ详解

17.1 AspectJ中切入点表达式

  • 语法:@Before(value="execution(权限修饰符  返回值类型  包名.类名.方法名(参数类型))")
  • 通配符
    • 【*】:
      • 【*】:可以代表任意权限修饰符&返回值类型
      • 【*】:可以代表任意包名,任意类名,任意方法名
    • 【..】:
      • 【..】:代表任意参数类型及参数个数
  • 重用切入点表达式

        1.使用@PointCut注解,提取可重用的切入点表达式

        2.使用方法名()引入切入点表达式

17.2 AspectJ中JoinPoint对象

  • JoinPont【切入点对象】
  • 作用:
    • 获取方法名称
      //获取方法签名【方法签名=方法名+参数列表】
      joinPoint.getSignature();
      //获取方法名称
      String methodName = joinPoint.getSignature().getName();
    • 获取参数
      Object[] args = joinPoint.getArgs();

17.3 AspectJ中通知

  • 前置通知
    • 语法:@Before
    • 执行时机:指定方法执行之前执行【如目标方法中有异常,会执行】
      • 指定方法:切入点表达式设置位置
    • 示例代码
  • 后置通知

    • 语法:@After

    • 执行时机:指定方法所有通知执行之后执行【如目标方法中有异常,会执行】

    • 示例代码

  • 返回通知

    • 语法:@AfterReturnning

    • 执行时机:指定方法返回结果时执行,【如目标方法中有异常,不执行】

    • 注意事项:@AfterReturnning中returnning属性与入参中参数名一致

    • 示例代码

  • 异常通知

    • 语法:@AfterThrowing

    • 执行时机:指定方法出现异常时执行,【如目标方法中无异常,不执行】

    • 注意事项:@AfterThrowing中的throwing属性值与入参参数名一致

    • 示例代码:

    • 总结

      • 有异常:前置通知=》异常通知=》后置通知

      • 无异常:前置通知=》返回通知=》后置通知

  • 环绕通知【前四个通知整合】

    • 语法:@Around

    • 作用:整合前四个通知

    • 注意:

      • 参数中必须使用ProceedingJoinPoint

      • 环绕通知必须将返回结果,作为返回值

    • 示例代码:

17.4 定义切面优先级

  • 语法:@Order(value=index)
    • index是int类型,默认值是int可存储的最大值
    • 数值越小,优先级越高【一般建议使用正整数】
  • 示例代码

 17.5 基于XML方式配置AOP(了解)

 第十八章 Spring 中 JdbcTemplate

18.1 JdbcTemplate简介

  • Spring提供的JdbcTemplate是一个小型的持久化层框架,简化Jdbc代码
    • MyBatis是一个半自动化的ORM持久化层框架

18.2 JdbcTemplate基本使用

  • 导入jar包
  • 编写配置文件
    • db.properties:设置连接数据库属性
    • applicationContext.xml【spring配置文件】
      • 加载外部属性文件
      • 装配数据源【DataSources】
      • 装配JdbcTemplate
    • 示例代码:
  • 使用核心类库【JdbcTemplate】

18.3 JdbcTemplate的常用API

  • jdbcTemplate.update(String sql,Object... args):通用的增删改方法
  • jdbcTemplate.batchUpdate(String sql,List<Object[]> args):通用的批处理增删改方法
  • jdbcTemplate.queryForObject(String sql,Class clazz,Object... args):查询单个数值
    • String sql = "select count(1) from tbl_xxx";
  • jdBCTemplate.queryForObject(String sql,RowMapper<T> rm,Object... args):查询单个对象
    • String sql = "select col1,col2... from tbl_xxx";
  • jdbcTemplate.query(String sql,RowMapper<T> rm,Object... args):查询多个对象

18.4 使用JdbcTemplate搭建Service&Dao层

  • Service层依赖Dao层
  • Dao层依赖JdbcTemplate
  • 示例代码

第十九章 Spring声明式事务管理

回顾事务

  1.事务四大特征【ACID】

  • 原子性
  • 一致性
  • 隔离性
  • 持久性

  2.事务三种行为

  • 开启事务:connection.setAutoCommit(false)
  • 提交事务:connection.commit()
  • 回滚事务:connection.rollback()                  

19.1 Spring中支持事务管理

  • 编程式事务管理【传统事务管理】
    • 获取数据库连接Connection对象
    • 取消事务的自动提交【开启事务】
    • 执行操作
    • 正常完成操作时手动提交事务
    • 执行失败时回滚事务
    • 关闭相关资源
    • 不足:
      • 事务管理代码【非核心业务】与核心业务代码相耦合
        • 事务管理代码分散
        • 事务管理代码混乱
    • 声明式事务管理【使用AOP管理事务
      • 先横向提取【事务管理代码】,再动态织入

19.2 使用声明式事务管理

不用事务管理代码,发现:同一个业务中,会出现局部成功及局部失败的现象【不正常】

  • 添加支持【AspectJ的jar包】
  • 编写配置文件
    • 配置事务管理器
    • 开启事务注解支持
  • 在需要事务管理的业务方法上,添加注解@Transactional
  • 总结:
    • 添加声明式事务管理之后,获取的是代理对象,代理对象不能转化为目标对象【实现类】

 19.3 Spring声明式事务管理属性

@Transactional注解属性

  •  事务传播行为【Propagation】
    • 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播
      • 如:执行事务方法method()1【事务x】之后,调用事务方法method2()【事务y】,此时需要设置method()2方法的事务传播行为
    • Spring的7中传播行为
    • 图解事务传播行为
      • REQUIRED
      • REQUIRED_NEW
      • 使用场景
  • 事务隔离级别【Isolation】
    • ​​​​​​​隔离级别概述:一个事务与其他事务之间的隔离等级【1,2,4,8】
    • 隔离等级:
      • 读未提交【1】:READ UNCOMMITTED
        • 存在问题:脏读【读取到了未提交数据】
      • 读已提交【2】:READ COMMITTED
        • 存在问题:可能出现不可重复读
      • 可重复读【4】:REPEATABLE READ
        • 存在问题:可能出现幻读
      • 串行化【8】:SERIALIZABLE

​​​​​​​

  • 事务超时【timeout】
    • 设置事务超时时间,到达指定时间后会强制事务回滚
    • 类型:int,单位:秒
    • 默认值:-1【未设置强制回滚时间】
  • 事务只读【readonly】
    • 一般事务方法中只有查询操作时,才将事务设置为只读
    • 默认值:false
  • 事务回滚【不回滚】
    • rollbackFor:设置回滚的异常Class
    • noRollbackFor:设置不回滚异常Class
  • 各种数据库产品对事务隔离级别的支持程度

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值