Spring是什么
Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性
Spring常用的注解有那些
Spring框架的好处
Spring 框架中都用到了哪些设计模式?
工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
单例模式:Bean默认为单例模式。
代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
观察者模式:定义对象键一种一对多的依赖关系,当一个对象的
Spring框架中有哪些不同类型的事件
Spring 提供了以下5种标准的事件:
上下文更新事件(ContextRefreshedEvent):在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。如果一个bean实现了ApplicationListener接口,当一个ApplicationEvent 被发布以后,bean会自动被通知。
Spring由那些模块组成
springIOC bean是如何初始化
Spring IOC 的好处有那些
Spring BeanFactory是什么?
Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;
Spring Application Context是什么?
应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能;
1 国际化(MessageSource)
2 访问资源,如URL和文件(ResourceLoader)
3 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层
4 消息发送、响应机制(ApplicationEventPublisher)
5 AOP(拦截器)
BeanFactory和AplicationContext的区别?
BeanFactory:
BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;
ApplicationContext:
ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化;
Spring获取AplicatinContext的方法?
1.通过WebApplicationUtils工具类获取,使用该方法的必须依赖Servlet容器。 方法如下:
ApplicationContext ap = WebApplicationUtils.getWebApplicationContext(servletContextParam)
2. 通过ClassPathXmlApplicationContext类获取。
ApplicationContext ap = new ClassPathXmlApplicationContext(“applicationContext.xml”);
3.创建一个自己的工具类(SpringContextUtil)实现Spring的ApplicationContextAware接口。最后在Spring配置文件中注册你的工具类。配置如下:
<bean id="springContextUtil" class="com.fubo.utils.spring.SpringContextUtil" lazy-init="false"/>
方式1要依赖Servlet容器,方式2实际只适合测试使用,方式1,2都有明显弊端。建议使用方式3
Spring依赖注入是什么?
Spring可以注入null和空字符串吗?
可以
Spring bean支持哪几种作用域?
singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
prototype : 每次请求都会创建一个新的 bean 实例。
request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
session : 每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效。
global-session: 全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经没有了。Portlet是能够生成语义代码(例如:HTML)片段的小型Java Web插件。它们基于portlet容器,可以像servlet一样处理HTTP请求。但是,与 servlet 不同,每个 portlet 都有不同的会话
Spring依赖注入有哪几种方式?
Spring bean生命周期是怎样的?
Bean 容器找到配置文件中 Spring Bean 的定义。
Bean 容器利用 Java Reflection API 创建一个Bean的实例。
如果涉及到一些属性值 利用 set()方法设置一些属性值。
如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入Bean的名字。
如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。
如果Bean实现了 BeanFactoryAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoade r对象的实例。
与上面的类似,如果实现了其他 *.Aware接口,就调用相应的方法。
如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法
如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
如果有和加载这个 Bean的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法
当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。
当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法
spring bean默认是单例还是多例?
spring的Bean默认的是单例的,Bean的作用域可以通过Bean标签的scope属性进行设置,Bean的作用域包括
Spring bean为什么默认为单例?
Spring bean怎么配置为多例模式?
Spring bean是线程安全的吗?
1.非线程安全
2.大部分时候我们并没有在系统中使用多线程,所以很少有人会关注这个问题。单例 bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。
3.常见的有两种解决办法:
在Bean对象中尽量避免定义可变的成员变量(不太现实)。
在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。
Spring bean怎么设置为默认bean?
Spring怎么防止相同类型bean注入异常?
1 使用org.springframework.beans.factory.annotation.Qualifier指定具体的beanName来匹配
2 使用@org.springframework.context.annotation.Primary注解
3 在类上使用@javax.annotation.Priority指定优先级
4 默认根据Field字段变量名匹配
5 使用@javax.annotation.Resource指定name,根据beanName注入
Spring如何在bean初始化时进行操作?
1.使用@PostConstruct注解,该注解作用于void方法上
2.在配置文件中配置init-method方法
3.将类实现InitializingBean接口
先执行@PostConstruct注解的方法,然后是实现了InitializingBean接口的afterPropertiesSet方法,最后执行在配置文件中配置的init-method方法
Spring如何在bean销毁时进行操作?
1 通过在Bean中定义init-method 和 destory-method方法
2 通过@PostConstruct和@PreDestroy方法实现初始化和销毁bean之前进行的操作
3 通过bean实现InitializingBean和DisposableBean接口
Spring中的@Bean与@Component注解的区别?
1,@Componnet是用在类上,声明这个类是一个组件被spring管理起来
2. @Bean作用在方法上,一般标明返回的对象直接被Spring管理起来
同:都是声明一个类被Spring管理起来。
不同点:作用target不同
Spring中的@Bean与@Component注解用在同一个类上,会怎么样?容器中有几个Bean?
Spring @Autowired注解有什么用?
@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。@Autowired 注解提供了更细粒度的控制,包括在何处以及如何完成自动装配。它的用法和@Required一样,修饰setter方法、构造器、属性或者具有任意名称和/或多个参数的PN方法。
@Autowired注入request线程安全吗?
由@Autowired注入的共享变量request并不存在线程安全问题
@Resource @Autowired,@Inject的区别?
共同点: 1.装配bean 2.写在字段上 3.写在setter方法上
差异点:
Autowired可用于:构造函数、成员变量、Setter方法
Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。
@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。
@Autowired、@Inject用法基本一样,不同的是@Autowired有一个request属性
Spring @Required注解有什么用?
这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配,若@Required注解的bean属性未被设置,容器将抛出BeanInitializationException
Spring @Qualifier注解有什么用?
当您创建多个相同类型的 bean 并希望仅使用属性装配其中一个 bean 时,您可以使用@Qualifier 注解和 @Autowired 通过指定应该装配哪个确切的 bean 来消除歧义。
Spring怎么注入Java集合类型?
Spring提供以下几种集合的配置元素:
类型用于注入一列值,允许有相同的值。
类型用于注入一组值,不允许有相同的值。
类型用于注入一组键值对,键和值都可以为任意类型。
类型用于注入一组键值对,键和值都只能为String类型。
Spring怎样开启注解装配
注解装配在默认情况下是不开启的,为了使用注解装配,我们必须在Spring配置文件中配置 context:annotation-config/元素
Spring装配是指什么?
装配,或bean 装配是指在Spring 容器中把bean组装到一起,前提是容器需要知道bean的依赖关系,如何通过依赖注入来把它们装配到一起。
什么是bean的自动装配
在Spring框架中,在配置文件中设定bean的依赖关系是一个很好的机制,Spring 容器能够自动装配相互合作的bean,这意味着容器不需要和配置,能通过Bean工厂自动处理bean之间的协作。这意味着 Spring可以通过向Bean Factory中注入的方式自动搞定bean之间的依赖关系。自动装配可以设置在每个bean上,也可以设定在特定的bean上。
Spring自动装配有哪些方式?
1 no:默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配bean。
2 byName:通过bean的名称进行自动装配,如果一个bean的 property 与另一bean 的name 相同,就进行自动装配。
3 byType:通过参数的数据类型进行自动装配。
4 constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配。
5 autodetect:自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。
Spring自动装配有什么局限性?
1 重写:你仍需用 和 配置来定义依赖,意味着总要重写自动装配。
2 基本数据类型:你不能自动装配简单的属性,如基本数据类型,String字符串,和类。
3 模糊特性:自动装配不如显式装配精确,如果有可能,建议使用显式装配。
Spring循环依赖是指什么?
一定是指默认的单例Bean中,属性相互引用的场景。Prototype的场景不支持循环依赖,会报错
Spring允许循环依赖吗?
Spring是如何解决循环依赖的?
Spring解决循环依赖的关键就是在处理Bean的属性依赖时,先将Bean存到三级缓存中,当存在循环依赖时,从三级缓存中获取到相关Bean,然后从三级缓存中移除,存入到二级缓存中,最后初始化完毕后存入到一级缓存中。
Spring怎么禁用循环依赖?
Spring为何需要三级缓存解决循环依赖,而不是二一级缓存?
查找位置从一级缓存至三级缓存,注意若三级缓存查找成功,其返回的bean对象并不一定是完全体,而可能是仅完成实例化,还未完成属性装填的提前暴露引用。当三级缓存内都未找到目标,getSingleton方法则会返回null,之后Spring将会执行一系列逻辑,最终将调用以下方法新创建bean对象:
使用三级缓存而非二级缓存并不是因为只有三级缓存才能解决循环引用问题,其实二级缓存同样也能很好解决循环引用问题。使用三级而非二级缓存并非出于IOC的考虑,而是出于AOP的考虑,即若使用二级缓存,在AOP情形下,注入到其他bean的,不是最终的代理对象,而是原始对象。
Spring AOP是什么?
Spring AOP有什么作用?
Spring AOP有哪些实现方式?
Spring AOP和AspectJ AOP的区别?
Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,
如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比Spring AOP 快很多。
Spring AspectJ有哪几种通知注解?
Spring AspectJ通知注解的执行顺序是?
Spring支持哪些事务管理类型?
① PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
② PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
③ PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
④ PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行
Spring用哪种事务管理类型比较合适?
Spring用什么注解开启事务?
1.将方法用@Trasactional注解,默认捕获RuntimeException的异常并触发方法中所有数据库操作(增、删、改)回滚。如果自定义异常需要设置,@Transactional(rollbackOn = Exception.class)
2.在配置文件中或者启动类上开始事务。
Spring事务默认回滚的异常是什么?
Spring事务怎么指定回滚的异常?
@Transaction(RollbackFor=Exception.class)
Spring事务怎么指定不回滚的异常?
@Transaction(noRollbackFor=RuntimeException.class)
Spring事务失效的原因有哪些?
1、数据库引擎不支持事务
2、没有被 Spring 管理 (这个类就不会被加载成一个 Bean,那这个类就不会被 Spring 管理了,事务自然就失效了)
3 方法不是 public 的 (如果要用在非 public 方法上,可以开启 AspectJ 代理模式)
4、数据源没有配置事务管理器
5 不支持事务
自身调用问题 Propagation.NOT_SUPPORTED: 表示不以事务运行,当前若存在事务则挂起,详细的可以参考《事务隔离级别和传播机制》这篇文章。都主动不支持以事务方式运行了,那事务生效也是白搭!
6 异常被吃了
7 异常类型错误
8 自身调用问题
8 例子 1
@Service
public class OrderServiceImpl implements OrderService {
public void update(Order order) {
updateOrder(order);
}
@Transactional
public void updateOrder(Order order) {
// update order
}
}
例子 2
@Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void update(Order order) {
updateOrder(order);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateOrder(Order order) {
// update order
}
}
例子1 update方法上面没有加 @Transactional 注解,调用有 @Transactional 注解的 updateOrder 方法,updateOrder 方法上的事务管用吗?
例子2 这次在 update 方法上加了 @Transactional,updateOrder 加了 REQUIRES_NEW 新开启一个事务,那么新开的事务管用么?
这两个例子的答案是:不管用!
因为它们发生了自身调用,就调该类自己的方法,而没有经过 Spring 的代理类,默认只有在外部调用事务才会生效,这也是老生常谈的经典问题了。
这个的解决方案之一就是在的类中注入自己,用注入的对象再调用另外一个方法,这个不太优雅,另外一个可行的方案可以参考《Spring 如何在一个事务中开启另一个事务?》这篇文章。
Spring只读事务(readOnly)是什么?
1<tx:method name=“search*” read-only=“true” />
2 @Transactional(readOnly = true)
Spring只读事务(readOnly)的应用场景?
Spring怎么配置只读事务?
Spring超时事务(timeout)是什么?
Spring怎么配置超时事务?
Spring怎么开启方法异步执行?
1@EnableAsync注解即开启Spring对方法异步执行的能力,需要和注解@Configuration配合使用
2在要异步执行的方法上使用@Async注解,下面是一个没有返回值,一个带有返回值的异步调用的示例。
使用注意
@Async只能使用到被代理的对象方法上,即代理类的入口方法处,且方法必须是public的。
事务处理机制
使用@Async异步注解不能和@Transaction事务注解在同一个方法上同时使用,不然事务注解将无效。
要使用事务,需要把事务注解提取到方法里面的子方法上。
Spring怎么开启定时任务?
Spring为什么不建议使用默认线程池?
Spring中的Aware接口有啥用?
Spring常用的Aware接口有哪些?
Spring中的@Enable*有什么用?
@Enable** 注解,一般用于开启某一类功能。类似于一种开关,只有加了这个注解,才能使用某些功能