Spring面试(一)

现在基本上企业开发标配都是Spring5+Springboot2+Jdk7

1.Spring的优点

  1. IOC和DI的支持:Spring的核心是一个工厂容器,可以维护所有对象的创建和依赖关系,Spring工厂用于生成bean,并且管理Bean的生命周期, 实现高内聚低耦合的设计理念。
  2. AOP编程的支持:Spring提供面向切面编程,可以方便的实现对程序的权限拦截,运行切面等功能。
  3. 声明式事务支持:支持通过配置就来完成对事务的管理,而不需要通过硬编码的方式,以前重复的一些事务提交,回滚的JDBC代码
  4. 快捷测试的支持:Spring对Junit提供支持,可以通过注解快捷的测试Spring程序。
  5. 快速的集成开发:方便集成各种开发框架,Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz 等)的直接支持。
  6. 复杂的API模板封装:Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等)都提供了模板化的封装,这些封装 API的提供使得应用难度大大降低。

2.Spring有哪些模块

主要的7大模块:

  1. Spring Core:Spring核心,他是框架最基础的部分,提供IOC和依赖注入DI的特性
  2. Spring Context :Spring上下文容器,它是BeanFactory功能加强的一个子接口。
  3. Spring Web:它提供Web应用开发的支持。
  4. SpringMVC :它针对Web应用中MVC思想的实现。
  5. SpringDAO:提供了JDBC抽象层,简化了JDBC编码
  6. Spring ORM:它支持用于流行的OPRM框架整合,比如:Spring + Hibernate、Spring + iBatis、Spring + JDO 的整合等。
  7. Spring AOP:即面向切面编程,它提供了与AOP联盟兼容的编程实现

3.Spring有那些注解。

容器

  • @Component:表示一个带注释的类是一个"组件",成为 Spring 管理的 Bean。当使用基于注解的配置和类路径扫描时,这些类被视为自动检测的候选对象。同时@Component 还是一个元注解。
  • @Service:组合注解(组合了@Component 注解),应用在 service 层(业务逻辑层)。
  • @Repository:组合注解(组合了@Component 注解),应用在 dao 层(数据访问层)。
  • @Autowired:Spring 提供的工具(由 Spring 的依赖注入工具(BeanPostProcessor、 BeanFactoryPostProcessor)自动注入)。
  • @Qualifier:该注解通常跟 @Autowired 一起使用,当想对注入的过程做更多的控制,@Qualifier 可帮助配置,比如两个以上相同类型的 Bean 时 Spring 无法抉择,用到此注解
  • @Configuration:声明当前类是一个配置类(相当于一个 Spring 配置的 xml 文件)
  • @Value:可用在字段,构造器参数跟方法参数,指定一个默认值,支持SpringbBoot 中的application.properties 配置的属性值赋值给变量
  • @Bean:注解在方法上,声明当前方法的返回值为一个 Bean。返回的 Bean 对应的类中可以定义 init()方法
    和 destroy()方法,然后在 @Bean(initMethod="init",destroyMethod="destroy")定义,在构造之后执行 init,在销毁之前执行 destroy。
  • @Scope:定义我们采用什么模式去创建 Bean(方法上,得有@Bean) 其设置类型包括:Singleton 、
    Prototype、Request 、 Session、GlobalSession。

AOP:

  • @Aspect:声明一个切面(类上) 使用@After、@Before、@Around 定义建言(advice),可直接将拦截规则(切点)作为参数。
    • @After:在方法执行之后执行(方法上)。
    • @Before: 在方法执行之前执行(方法上)。
    • @Around: 在方法执行之前与之后执行(方法上)。
    • @PointCut: 声明切点 在 java 配置类中使用@EnableAspectJAutoProxy 注解开启 Spring 对 AspectJ
      代理的支持(类上)。

事务:

  • @Transactional:在要开启事务的方法上使用@Transactional 注解,即可声明式开启事务。

4.Spring的常用注解

  • 工厂模式:Spring本质上就是一个大工厂,使用工厂模式通过BeanFactory,ApplicationContent创建bean对象
  • 代理模式:Spring Aop功能就是通过代理模式实现的,分为动态代理和静态代理
  • 单例模式:Spring 中的Bean默认都是单例的,这样有利于容器对Bean的管理。
  • 模板模式:Spring中的JdbcTemplate,RestTemplate等以Template结尾的对数据库,网络等操作的模板类,就是使用到了模板模式。
  • . 适配器模式 :Spring AOP 的增强或通知 (Advice) 使用到了适配器模式、Spring MVC 中也是用到了适配器模式适配 Controller。
  • 策略模式:Spring中有一个Resource接口,它的不同实现类,会根据不同的策略去访问资源。

5.什么事IOC,什么是DI

  1. 所谓的IOC(控制反转),就是由容器来负责控制对象的生命周期和对象的关系,以前是我们想要什么就创建什么,现在是我们需要什么就送来什么。
    也就是说,控制对象的生命周期的不再引用它的对象,而是容器。对具体的对象以前是它控制其他对象,现在所有对象都被容器控制,所以这叫控制反转。

2.DI(依赖注入):指的是容器在实例化对象的时候把它依赖的类注入给它,有的说法是DI和IOC是一回事,也有说法IOC是思想,DI是IOC的实现类。

为什么要用IOC呢
最主要的是为了解耦,硬编码会造成对象之间的过度耦合,使用了IOC之后,我们就不要关心对象之间的依赖,专心开发应用就行。

6.能简单说一下 SpringIOC的实现机制吗?

PS:这道题在面试中被问到过,问法是"你有自己实现过简单的 Spring 吗?"

7.说说BeanFactory和ApplicantContext?

可以这么形容,BeanFactory是Sprin的心脏,Applicantext是完整的身躯

  • BeanFactory(Bean工厂)是Spring框架的的基础设施,面向Spring本身
  • ApplicantContext是建立在BeanFactory的基础上,面向使用的Spring框架的开发者。

BeanFactory接口

BeanFactory是类的通用工厂,可以创建并且管理各种类的对象

Spring为BeanFactory提供了很多种实现,最常用的是xmlBeanFactory,但是在Spring3.2中已被废弃,建议使用XmlBeanDefinitonReader,DefaultListBeanFactory

  • BeanFactory接口位于类结构树的顶端,它最主要的方法是getBean(String var)这个方法从特定容器中返回特定名称的Bean。
  • BeanFactory 的功能通过其它的接口得到了不断的扩展,比如 AbstractAutowireCapableBeanFactory 定义了将容器中的
    Bean 按照某种规则(比如按名字匹配、按类型匹配等)进行自动装配的方法。

ApplicationContext接口

ApplicationContext是由BeaFactory派生而来,提供更多了面向实际的功能,可以这么说,使用

BeanFactory 就是手动档,使用 ApplicationContext 就是自动档。

ApplicationContext 继承了HierachicalBeanFactory 和 ListableBeanFactory 接口,在此基础上,还通过其他的接口扩展

了BeanFactory 的功能,包括:

  • Bean instantiation/wiring
  • Bean 的实例化/串联
  • 自动的 BeanPostProcessor 注册
  • 自动的 BeanFactoryPostProcessor 注册方便的 MessageSource 访问(i18n)
  • ApplicationEvent 的发布与 BeanFactory 懒加载的方式不同,它是预加载,所以,每一个 bean 都在ApplicationContext 启动之后实例化
    这是 ApplicationContext 的使用例子
java 复制代码
public class HelloWorldApp{
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}

ApplicationContext包含了BeanFactory的所有特性,所以一般推荐使用前者

8. 你知道Spring容器启动阶段会干什么吗

Spring的IOC容器工作过程,其实可以分为两阶段,容器启动阶段和Bean的实例化阶段 ,其中容器启动阶段主要工作是加载和解析配置文件,保存到对应的Bean中。

容器 启动阶段,首先会通过某种途径加载Congiguration MetaData,在大部分情况下,容器需要依赖某些工具类,对加载的Conguguration MetaData进行解析和分析,并将分析后的信息组织为相应的BeanDefinition。

最后把这些的Bean定义必要信息的BeanDefiniton,注册到相应的BeanDefinitionRegistry,这样容器就完成了

9.能说下SpringBean的生命周期吗

SpringIOC的生命周期大致分为 实力化、属性赋值、初始化、销毁

10.Bean定义和依赖定义有哪几种方式

有三种方式: 直接编码方式、配置文件方式、注解方式。

  • 直接编码方式:我们一般接触不到直接编码方式,但是其他方式最终都要通过直接编码来实现。
  • 配置文件方式:通过XML、propreties类型的配置文件,配置相应的依赖关系,Spring读取配置文件,完成依赖关系的注入。
  • 注解方式:注解方式应该是我们用过最多的一种方式,在相应的地方进行注解,Spring会扫描注解,完成依赖关系的注入。

11 有哪些 依赖注入的方法

Spring支持的构造方法注入、属性注入、工厂方法注入、其中工厂方法注入又可以分为 静态工厂注入和非静态方法注入。

12.Spring有那些自动装配的方式

Spring提供了4种自动装配类型:byType,byName,constructor,autodetect

  • byName:根据名称进行自动匹配,假设 Boss 又一个名为 car 的属性,如果容器中刚好有一个名为 car 的bean,Spring就会自动将其装配给 Boss 的 car 属性
  • byType:根据类型进行自动匹配,假设 Boss 有一个 Car 类型的属性,如果容器中刚好有一个 Car 类型的Bean,Spring 就会自动将其装配给 Boss 这个属性
  • constructor:与 byType 类似, 只不过它是针对构造函数注入而言的。如果 Boss 有一个构造函数,构造函数包含一个 Car 类型的入参,如果容器中有一个 Car 类型的 Bean,则 Spring 将自动把这个 Bean 作为 Boss构造函数的入参;如果容器中没有找到和构造函数入参匹配类型的 Bean,则 Spring 将抛出异常。
  • autodetect:根据 Bean 的自省机制决定采用 byType 还是 constructor 进行自动装配,如果 Bean 提供了默认的构造函数,则采用 byType,否则采用 constructor。

13.Spring中的Bean的作用域

14.Spring中的单例Bean存在线程安全吗

Spring中的Bean不是线程安全的。
因为单例Bean,是全局只有一个 Bean,所有线程共享 。如果说单例Bean,是一个无状态的,也就是线程中的操作不会对 Bean 中的成员变量执行查询以外的操作,那么这个单例Bean 是线程安全的。比如 Spring mvc 的 Controller、

Service、Dao 等,这些 Bean 大多是无状态的,只关注于方法本身。

假如这个 Bean 是有状态的,也就是会对 Bean 中的成员变量进行写操作,那么可能就存在线程安全的问题。

常见的解决方法:

1.将Bean定义为多例:这样每一个线程请求都会创建一个Bean,但是这样就不好管理了,不能这样干

2。在bean对象中尽量避免定义可变的成员变量,但是这不符合开发要求,也不能这样干。

3.将Bean中成员变量保存在ThreadLocal中。

因为ThreadLocal能保证多线程下的变量隔离可以在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在Threadlocal中,这个是推荐使用的方式。

15.@Autowired的实现原理。

实现@Autowired的关键是AutowiredAnnotationBeanPostProcessor

在Bean的初始化阶段,会通过Bean后置处理器来进行一些前置和后置的处理,实现@Autowired的功能,也是通过后置处理器来完成了,这个后置处理器就是AutowiredAnnotationBeanPostProcessor

-Spring在创建 bean的过程中,最终会调用到 doCreateBean()方法,在 doCreateBean()方法中会调用populateBean()方法,来为 bean 进行属性填充,完成自动装配等工作。

  • 在 populateBean()方法中一共调用了两次后置处理器,第一次是为了判断是否需要属性填充,如果不需要进行属性
    填充,那么就会直接进行return,如果需要进行属性填充,那么方法就会继续向下执行,后面会进行第二次后
    置处理器的调用,这个时候,就会调用到 AutowiredAnnotationBeanPostProcessor 的 postProcessPropertyValues()方法,在该方法中就会进行@Autowired 注解的解析,然后实现自动装配
相关推荐
ExiFengs2 分钟前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring
瓜牛_gn35 分钟前
依赖注入注解
java·后端·spring
一元咖啡2 小时前
SpringCloud Gateway转发请求到同一个服务的不同端口
spring·spring cloud·gateway
ifanatic2 小时前
[面试]-golang基础面试题总结
面试·职场和发展·golang
程序猿进阶2 小时前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
java亮小白19973 小时前
Spring循环依赖如何解决的?
java·后端·spring
苏-言4 小时前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring
草莓base4 小时前
【手写一个spring】spring源码的简单实现--容器启动
java·后端·spring
长风清留扬4 小时前
一篇文章了解何为 “大数据治理“ 理论与实践
大数据·数据库·面试·数据治理
冰帝海岸10 小时前
01-spring security认证笔记
java·笔记·spring