打卡面试题-Spring

什么是spring

Spring是java企业级应用的开源开发框架。Spring主要用来开发java应用,但是有些扩展是针对于J2EE平台的web应用。其目的是为了简化java企业级应用开发。

使用Spring框架的好处是什么

  • 轻量:基本的版本大约为2MB
  • 控制反转Ioc:spring通过控制反转实现了松散耦合。
  • 面向切面编程Aop:支持切面编程,并把应用业务逻辑和系统服务分开
  • 容器:Spring包含管理应用中对象的生命周期和配置
  • MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的代替品
  • 事务管理:提供了一个持续的事务管理接口,可以扩展到上到本地事务下到全局事务(JTA)
  • 异常处理:提供方便的API把具体技术相关的异常转换为一致的unchecked异常

Spring由哪些模块组成

  • Core module
  • Bean module
  • Context module
  • Expression Language module
  • JDBC module
  • OXM module
  • Java Messaging Service(JMS) module
  • Transaction module
  • Web module
  • Web-Servlet module

Spring是怎样解决循环依赖的

Ioc容器解决循环依赖,用到的几个重要成员:
singletonObjects:一级缓存,存放完全初始化好的Bean的集合,从这个集合中取出来的bean可以立即返回
EarlySingletonObjects:二级缓存,存放创建好但没有初始化属性的Bean的集合,它用来解决循环依赖
singletonFactioies:三级缓存,存放单实例Bean工厂的创建
singletonCurrentlyCreation:存放正在创建的Bean的集合

Ioc容器解决循环依赖的思路

  1. 初始化bean后,将该beanName放入三级缓存
  2. 创建bean将准备创建的bean放入singletonCurrentlyFactory
  3. createNewInstance方法执行addSingletonFactory,将这个实例化但没有属性赋值的bean放入二级缓存,从三级缓存中移除
  4. 属性赋值&自动注入,依法关联创建
  5. 关联创建时,检查正在被创建的bean中是否有即将注入的bean。如果有,检查二级缓存是否有当前创建好但没有赋值初始化的bean,如果没有,检查三级缓存中是否有正在创建的bean。一般都会有,将这个bean放入二级缓存,并从三级缓存中移除
  6. 之后bean被成功注入,之后执行addSingleton,将这个完全创建好的bean放入一级缓存,从二级缓存和三级缓存移除,并记录一经创建了的单实例bean

SpringBoot手动装配有哪几种方式

  1. 使用注解模式@Component等
  2. 使用配置类@Configuration与@Bean
  3. 使用模块注解@EnableXXX与@Import

谈谈自己对Spring Ioc的理解

Ioc(Inversion Of Controll,控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交给Spring框架来管理。Ioc在其他语言中也有应用,并非Spring特有。Ioc容器是Spring用来实现Ioc的载体,Ioc容器实际上就是一个Map(key,value),Map中存放将对象之间的相互依赖关系交给Ioc来管理,并由Ioc容器来完成对对象的注入。这样可以很大程度简化应用的开发,把应用从复杂的依赖关系中解放出来。Ioc容器就是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来。

谈谈自己对Spring Aop的理解

Aop(Aspect-Oriented Programming,面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务管理,日志管理,权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可扩展性和可维护性。
Aop 是基于动态代理的,如果要代理的对象实现了某个接口,那么Spring aop就会使用jdk动态代理去创建代理对象,而对于没有实现接口的对象会使用cglib动态代理生成一个代理对象的子类来作为代理。
使用Aop之后我们可以把一些同用功能抽象出来,在需要用到的地方直接使用即可,这样可以大大简化代码量。我们需要增加新功能也方便,提高了系统的扩展性。日志功能,事务管理和权限管理等场景都用到了Aop

Spring AOP和AspectJ AOP有什么区别

Spring aop是属于运行时增强,而AspectJ是编译时增强。
Spring aop基于代理,而AspectJ基于字节码操作
Spring aop集成了AspectJ,AspectJ算是java生态系统中最完整的aop框架。AspectJ相比于Spring aop功能更强大,但是Spring aop相对来说更简单
如果项目中的切面比较少,两者差异性不大。但是,当切面太多的话,最好选择AspectJ,它比Spring aop块。

Spring中的bean的作用域有哪些

  1. singleton:唯一bean实例,spring中的bean都是单例的
  2. prototype:每次请求都会创建一个新的bean实例
  3. request:每一次Http请求都会产生一个新的bean,该bean仅在当前Http request内有效
  4. session:每一次请求Http请求都会产生一个新的bean,该bean仅在当前Http session内有效
  5. global-session:全局session作用域,仅仅在基于Portlet的web应用中才有意义,Portlet是能够生成语义代码片段的小型java web插件,它是基于portlet容器,可以向Servlet一样处理Http请求。但是与Servlet不同,每个Portlet都有不同的会话。

Spring中的单例bean的线程安全了解吗

大部分时候我们并没有以在系统中使用多线程,所以很少有人会关注这个问题。单例bean存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。
解决方案:

  1. 在bean对象中尽量避免定义可变的成员变量(不太现实)
  2. 在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal(推荐使用)

Spring中的bean声明周期了解过吗

  1. Bean容器找到配置文件中Spring Bean的定义
  2. Bean容器利用java Reflection API创建一个Bean的实例
  3. 如果涉及到一些属性值,利用set()方法设置一些属性值
  4. 如果Bean实现了BeanNameAware接口,调用setBeanName(),传入Bean的名字
  5. 如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例
  6. 如果Bean实现了BeanFactoryAware接口,嗲用setBeanClassFactory()方法,传入ClassLoader对象的实例
  7. 与上面的类类似,如果实现了其他*Aware接口,就调用相应的方法
  8. 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor()对象,执行postProcessBeforeInitialization()方法
  9. 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法
  10. 如果Bean在配置文件中的定义包含init-method属性,执行指定的方法
  11. 如果有和加载这个Bean的Spring容器相关的BeanPostProcess对象,执行postProcessAfterInitialization()方法
  12. 当要销毁Bean的时候,如果Bean实现了DisPOSableBean接口,执行destory()方法
  13. 当要销毁Bean的时候,如果Bean在配置文件中的定义包含destory-method属性,执行指定的方法。

Spring MVC的工作原理了解吗

  1. 客户端(浏览器)发送请求,直接请求到DispatcherServlet
  2. DispatcherServlet根据请求调用HandlerMapping,解析请求对应的Handler
  3. 解析到对应的Handler(也就是常说的Controller控制器)
  4. HandlerAdapter会根据Handler来调用真正的处理器来处理请求和执行相应的业务逻辑
  5. 处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是逻辑上的View
  6. ViewResolver会根据逻辑View其查找实际的View
  7. DispatcherServlet把返回的Model传给View(视图渲染)
  8. 把View返回给调用者

Spring框架中用到了那些设计模式

  1. 工厂设计模式:Spring使用工厂模式通过BeanFactory和ApplicationContext创建bean对象
  2. 代理设计模式:Spring AOP功能的实现
  3. 单例设计模式:Spring中的bean默认都是单例的
  4. 模板方法模式:Spring中的jdbcTemplate,HibernateTemplate等以Template结尾的对数据库操作的类,他们都使用了模板模式
  5. 包装器设计模式:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根矩需要访问不同的数据库,这种模式让我们可以根据客户的需求能够动态切换不同的数据源
  6. 观察者模式:Spring事件驱动模型九十观察者模式很经典的一个应用
  7. 适配器模式:Spring Aop的增强或通知(Advice)使用了适配器模式,Spring MVC中也是用到了适配器模式适配Controller

@Component和@Bean的区别是什么

  1. 作用对象不同。@Component注解用于类,@Bena注解作用于方法
  2. @Component注解通常是通过类路径来扫描来自动侦测以及动配置到Spring容器中(我们可以使用@ComponentScan注解定义要扫描的路径)。@Bean注解通常是在标有该注解的方法中定义产生这个bean,告诉Spring这个类的实力,当我们需要它的时候还给我。
  3. @Bean注解比@Component注解的自定义性更强,而且很多地方只能通过@Bean注解来注册bean,如果引用第三方库的类需要装配到Spring容器的时候,就只能通过@Bean注解来实现。

将一个类声明为Spring的bean的注解有哪些?

当我们使用@Autowire注解去自动装配bean,而想象把一个类表示为可以用@Autowire注解自动装配bean,可以使用以下的注解实现:

  1. @Component注解。通用的注解,可以标注任意类为Spring组件。如果一个bean不知道属于哪一层,可以使用@Component注解标注
  2. @Repository注解,对应持久层,即Dao层,主要用于数据库相关操作
  3. @Service注解,对应服务层,即Service层,主要涉及一些复杂的逻辑,需要用到Dao层(注入)
  4. @Controller注解,对应Spring mvc的控制层,即Controller层,主要用于接收用户请求并调用Service层的方法返回数据给前端页面。

Spring事务管理的方式有几种

  1. 编程式事务:在代码中硬编码
  2. 声明式事务:在配置文件中配置(推荐使用),分为XML的声明式事务和基于注解的声明式事务

Spring事务中的隔离级别有几种

ISOLATION_DEFAULT:使用后端数据库默认的隔离级别,Mysql默认采用的
REPEATABLE_READ隔离级别;Oracle默认采用的READ_COMMITTED隔离级别。
ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重
复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

Spring事务中有几种事务传播行为

支持当前事务的情况:
PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)。不支持当前事务的情况:
PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。
其他情况:
PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于PROPAGATION_REQUIRED。

Spring事务底层原理

划分处理单元–IOC
由于spring解决的问题是对单个数据库进行局部事务管理,具体的实现首先用Spring中的IOC划分了事务处理单元。并且将对事务的各种配置放到了IOC中(设置事务管理器,设置事务的传播特性即隔离机制)
AOP拦截需要进行事务处理的类
Spring事务处理模块是通过AOP功能来实现声明式事务处理的,具体操作(比如事务实行的配置和读取,事务对象的抽象),用TransactionProxyFactoryBean接口来使用AOP功能,生成proxy代理对象,通过TransactionInterceptor完成对代理方法的拦截,将事务处理的功能编织到拦截的方法中。读取IOC容器事务配置属性,转换为spring事务处理需要的内部数据结构(TransactionAttributeSourceAdvisor),转换为TransactionAttribute表示的数据对象。
对事务处理实现(事务的生成,提交,回滚,挂起)
spring委托给具体的事务处理器实现。实现了一个抽象和适配。适配的具体事务处理器:DataSource数据源支持、hibernate数据源事务处理支持、JDO数据源事务处理支持、JPA、JTA数据源事务处理支持。这些支持都是通过设计PlatformTransactionManager、AbstractPlatformTransaction一些列的事务处理的支持。为常用数据源支持提供了一些列的TransactionManager
总结
PlatformTransactionManager实现了TransactionInterceptor接口,让其与TransactionPRoxyFactory结合起来,形成一个spring声明式事务处理的设计体系。

BeanFactory和ApplicaitionContext有什么区别

ApplicationContext提供了一种解决文档信息的方法,一种加载文件资源的方式(如图片),他们可以监听它们的Beans发送信息。另外,容器或者容器中beans的操作,这些必须以bean工厂的编程方式处理的操作可以在上下文中以声明的方式处理。应用上下文实现了MessageSource,该接口用于获取本地消息,实际的实现是可选的。
相同点:两者都是通过xml配置文件加载bean,ApplicationContext个beanFactory相比,提供了更多的扩展功能。
不同点:BeanFactory是延迟加载,如果bean的某一个属性没有注入,beanFactory加载后,直至第一次使用getBean方法才会报异常;而ApplicationContext则在初始化自身检验,这样有利于检查所依赖属性是否注入;所以通常我们选择使用ApplicationContext。

Rescource是如何被查找,加载的

Resource接口是Spring资源访问策略的抽象,它本身并不提供任何资源访问实现,具体的资源访问由该接口的实现类完成–每个实现类代表一种访问策略。Spring为Resource接口提供了如下实现类:
UrlResource::访问网络资源的实现类。
ClassPathResource:访问类加载路径里资源的实现类。
FileSystemResource:访问文件系统里资源的实现类
ServletContextResource:访问相对于ServletContext路径里的实现类
InputStreamResource:访问输入流资源的实现类等
这些Resource实现类,针对不同的底层资源,提供了相应的访问逻辑,并提供便捷的包装,以便于客户端程序的资源访问。

解释自动装配的各种模式

自动装配提供了五种不同的模式供spring容器用来自动装配bean之间的依赖注入

  1. no:默认的方式是不尽兴自动装配,通过手动设置ref属性来进行装配bean
  2. byName:通过参数名自动装配,spring容器查找beans的属性,这些beans在XML配置文件中被设置为byName。之后容器视图匹配,装配和该bean的属性具有相同名字的bean
  3. byType:通过参数的数据类型自动装配,spring容器查找beans的属性,这些beans在XML配置文件中被设置为byType。之后容器试图匹配和装配和该bean的属性类型一样的bean。如果多个bean符合条件,则抛出异常。
  4. constructor:这个同byType类似,不过是应用与构造函数的参数。如果在BeanFactory中不是恰好有一个bean与构造函数参数相同类型,则抛出一个严重的错误
  5. autodetect:如果有默认的构造方法,通过construct的方式自动装配,否则使用byType的方式自动装配。

有哪些不同的IOC(依赖注入)

  1. 构造器依赖注入:构造器依赖注入在容器触发构造器的时候完成,该构造器有一列的参数,每个参数代表注入的对象
  2. setter方法依赖注入:首先容器会触发一个无参构造函数或无参静态工厂方法实例化对象,之后容器调用bean中setter方法完成setter方法依赖注入

Spring AOP实现原理

实现AOP的技术,主要分为两大类:
一是采用动态代理,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,应用特点的语法创建“切面”,从而使得编译器可以在编译期间织入有关“切面”的代码。
Spring Aop的实现原理很简单:Aop框架负责动态地生成Aop代理类,这个代理类的方法由Advice和回调目标对象的方法所组成,并将该对象可作为目标对象使用。Aop代理包含了目标对象的全部方法,但Aop代理中的方法与目标对象的方法存在差异,Aop方法在特定切入点添加了增强处理,并毁掉了目标对象的方法。
Spring Aop使用动态代理技术在运行期织入增强的代码。使用两个代理机制:基于JDK的动态代理和基于CGLIB的动态代理。

  1. JDK的动态代理
    Jdk的动态代理主要涉及java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中InvocationHandler只是一个接口,可以实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态的将横切逻辑与业务逻辑织在一起。而Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。
    其代理对象必须是某个接口的实现,它是在运行期间创建一个接口的实现类来完成对目标对象的代理,只能实现接口的类生成代理,而不是针对类。
  2. Cglib
    Cglib采用底层的字节码技术,为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类的调用方法,并顺势织入横切逻辑,它运行期间生成的代理对象是目标类的扩展子类,所以无法通知final,private的方法,因为它们不能被复写,是针对类实现代理,主要是为了指定的类生成一个子类,覆盖其中的方法。
    在spring中默认情况下使用JDK动态代理实现Aop,如果proxy-target-class设置为true或者使用优化策略那么会使用Cglib来创建动态代理。Spring Aop在这两种方的实现上基本一样,以jdk代理为例,会使用jdkDynamicAopProxy来创建代理,在invoke()方法首先需要织入到当前类的增强器封装到拦截器链中,然后递归的调用这些拦截器完成成功的织入,最终返回代理对象。

ApplicationContext通常的实现类是什么

  1. FileSyatemXmlApplicationContext:此容器从一个XML文件中加载beans的定义,XML bean配置文件的全路径名必须提供给它的构造函数
  2. ClassPathXMLApplicationContext:此容器也从一个XML文件中加载beans的定义,这里,只需要正确设置classpath,因为这个容器将在classpath里找bean配置
  3. WebXmlApplicationContext:此容器加载一个XML文件,此文件定义了一个web应用的所有bean

Bean工厂和Application Contexts有什么区别

Application Contexts提供了一种方法处理文本消息,一个通常的做法是加载文件资源(比如镜像)他们可以向注册为监听器的bean发布事件。另外,在容器或容器内的对象上执行的那些不得不得由bean工厂以程序化方式处理的操作,可以在Application Contexts中以声明的方式处理。Application Contexts实现了MessageSource接口,该接口的实现以可插拔的方式提供获取本地化消息的方法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Boot可以通过钉钉机器人实现钉钉打卡功能。下面是一个简单的示例: 1. 首先,需要在pom.xml文件中添加钉钉机器人的依赖: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>dingtalk-sdk</artifactId> <version>1.0.0</version> </dependency> ``` 2. 创建一个钉钉机器人的配置类,用于配置机器人的Webhook地址和其他相关信息: ```java import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.dingtalk.chatbot.DingtalkChatbotClient; import com.dingtalk.chatbot.SendResult; import com.dingtalk.chatbot.message.TextMessage; @Configuration public class DingTalkConfig { @Value("${dingtalk.webhook}") private String webhook; @Bean public DingtalkChatbotClient dingtalkChatbotClient() { return new DingtalkChatbotClient(); } public void sendDingTalkMessage(String message) { DingtalkChatbotClient client = dingtalkChatbotClient(); TextMessage textMessage = new TextMessage(message); SendResult sendResult = client.send(webhook, textMessage); // 处理发送结果 } } ``` 3. 创建一个打卡服务类,用于发送打卡消息到钉钉机器人: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class CheckInService { @Autowired private DingTalkConfig dingTalkConfig; public void checkIn() { // 执行打卡逻辑 // ... // 发送打卡消息到钉钉机器人 dingTalkConfig.sendDingTalkMessage("今日打卡成功!"); } } ``` 4. 在需要打卡的地方调用打卡服务类的checkIn方法即可实现钉钉打卡功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

double_lifly

点喜欢就是最好的打赏!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值