spring常见面试题
一、*什么是Spring框架?
二、*Spring AOP和AspectJ AOP有什么区别?
2.1、Spring AOP
Spring 在运行期会为目标对象生成一个动态代理对象,并在代理对象中实现对目标对象的增强。Spring AOP 的底层是通过以下 2 种动态代理机制,为目标对象(Target Bean)执行横向织入的。
Spring AOP和AspectJ AOP都是面向切面编程(AOP)的实现方式,但它们在实现方式、灵活性、依赖性和应用场景等方面存在一些显著的区别。以下是详细的对比分析:
2.2、实现方式
- Spring AOP:
- 基于代理:Spring AOP使用动态代理技术(包括JDK动态代理和CGLIB)在运行时生成代理对象,并将切面逻辑织入到代理对象中。
- 代理机制:对于基于接口的目标类,Spring使用JDK动态代理;对于没有实现接口的目标类,Spring使用CGLIB生成子类来实现代理。
- AspectJ AOP:
- 基于字节码增强:AspectJ AOP在编译期或类加载期通过在目标类中直接插入字节码来实现切面逻辑的织入,不依赖于代理。
- 灵活性:AspectJ提供了更强大和灵活的AOP功能,允许进行更细粒度的控制和切入。
-
2.3、灵活性和依赖性
- Spring AOP:
- 依赖Spring:Spring AOP对Spring管理的Bean生效,基于代理的方式,支持更灵活的切点表达式。但由于是基于代理,它只能作用于Spring Bean的方法调用,无法应用于非Spring Bean的方法。
- 集成性:与Spring框架有较强的集成,依赖于Spring的容器和代理机制,在Spring项目中更容易集成和使用。
- AspectJ AOP:
- 不依赖Spring:AspectJ AOP作为独立的框架,不依赖于Spring,可以在任何Java项目中使用。
- 广泛应用:它可以对任何Java对象生效,不仅限于Spring管理的Bean,可以作用于所有的对象。
- 额外配置:需要在编译时或类加载时进行织入,可能需要额外的配置和依赖。
2.4、性能
- Spring AOP:
- 动态代理的性能:由于采用动态代理,对目标类的影响相对较小,因此性能相对较高。但对于大规模或频繁的切面逻辑,可能会有一些性能损耗。
- AspectJ AOP:
- 字节码增强的性能:通过编译时或类加载时织入,虽然对字节码进行了修改和增强,可能对目标类的影响更大,但在某些场景下可能性能更高。然而,这也取决于具体的实现和配置。
2.5、应用场景
- Spring AOP:
- 轻量级AOP需求:适用于轻量级的AOP需求,如日志记录、事务管理等,对Spring框架集成友好。
- AspectJ AOP:
- 复杂AOP需求:适用于复杂的AOP需求,如系统架构中需要对各个层次的组件进行切面,或者对非Spring Bean的对象进行切面等。
综上所述,选择Spring AOP还是AspectJ AOP取决于具体的项目需求和场景。如果需要更强大和灵活的AOP功能,并且可以接受一些额外的配置和依赖,那么AspectJ AOP可能更为适合。而对于大多数Spring项目来说,Spring AOP是一个常用且足够的选择。
三、*如何正解Spring IOC
对象的作用域scope
lazy_init默认值是false,在spring容器启动时创建对象,并且只在scope=singleteon时有效;
@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。
@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
四、***Spring中的bean的作用域有哪些?Spring中的单例bean的线程安全吗?
4.1、spring的bean作用域
singleton:单例模式,当spring创建applicationContext容器的时候,spring会欲初始化所有的该作用域实例,加上lazy-init就可以避免预处理;将一直存活到容器退出,也就是说,它与IoC容器“几乎”拥有相同的“寿命”。Spring默认bean的模式是单例模式,@Controller也是bean的一种,也是单例模式;
- 为什么spring bean要默认是单例呢?
1、减少对象创建开销,节省资源,提高性能。
2、简化依赖关系:在Spring框架中,Bean之间可能存在复杂的依赖关系。如果每次都创建新的Bean实例,可能会产生相互依赖的Bean获取不同实例的问题,从而破坏依赖关系。单例模式可以确保依赖关系的稳定性和一致性。
3、保证全局状态一致性,易于维护和测试:单例模式可以确保全局共享状态的一致性,避免了资源竞争和线程安全性问题。这有助于简化应用的维护和测试工作。
单例模式在多线程环境下存在线程安全问题!!!
prototype:原型模式,每次通过getBean获取该bean就会新产生一个实例,创建后spring将不再对其管理;
容器在接到该类型对象的请求的时候ÿ