11、spring 支持几种 bean scope?
- Spring bean 支持 5 种 scope:
- Singleton(单例)-:每个 Spring IoC 容器仅有一个单实例。
- Prototype(原型): 每次请求都会产生一个新的实例。
- Request(请求): 每一次 HTTP 请求都会产生一个新的实例,并且该 bean 仅在当前 HTTP 请求内有效。
- Session(会话): 每一次 HTTP 请求都会产生一个新的 bean,同时该 bean 仅在当前 HTTP session 内有效。
- Global-session(全局会话) -:类似于标准的 HTTP Session 作用域,不过它仅仅在基于portlet 的 web 应用中才有意义。Portlet 规范定义了全局 Session 的概念,它被所有构成某个 portlet web 应用的各种不同的 portlet 所共享。在 global session 作用域中定义的 bean 被限定于全局 portlet Session 的生命周期范围内。如果你在 web 中使用 global session 作用域来标识 bean,那么 web会自动当成 session 类型来使用。
- 仅当用户使用支持 Web 的 ApplicationContext 时,最后三个才可用。
12、Spring 容器的生命周期包括以下几个阶段:
- 实例化(Instantiation):当 Spring 容器启动时,它会根据配置信息实例化所有在配置文件中定义的 bean。
- 设置属性(Property Setting):在实例化 bean 后,Spring 容器会通过 bean 的属性注入(Dependency Injection)机制设置 bean 的属性值和其他依赖关系。
- Bean 初始化方法调用(Initialization) :在设置完所有属性之后,Spring 容器会调用在 bean 定义中配置的初始化方法(例如
@PostConstruct
标注的方法或者实现InitializingBean
接口的afterPropertiesSet()
方法),以执行一些初始化逻辑。 - Bean 可用(Bean is ready for use):初始化方法调用完成后,bean 就变为可用状态,可以被应用程序使用了。
- Bean 销毁(Bean Destruction) :当应用程序关闭时,Spring 容器会调用 bean 定义中配置的销毁方法(例如
@PreDestroy
标注的方法或者实现DisposableBean
接口的destroy()
方法),以执行一些清理工作。 - 销毁(Destruction):在销毁方法调用完成后,Spring 容器会销毁 bean 实例,释放资源。
- 这些阶段构成了 Spring 容器中每个 bean 的完整生命周期。通过钩子方法和回调接口,开发人员可以在生命周期的不同阶段插入自定义的逻辑,以满足特定需求。
13、spring bean 容器的生命周期是什么样的?
- spring bean 容器的生命周期流程如下:
- 1、Spring 容器根据配置中的 bean 定义中实例化 bean。
- 2、Spring 使用依赖注入填充所有属性,如 bean 中所定义的配置。
- 3、如果 bean 实现BeanNameAware 接口,则工厂通过传递 bean 的 ID 来调用setBeanName()。
- 4、如果 bean 实现 BeanFactoryAware 接口,工厂通过传递自身的实例来调用 setBeanFactory()。
- 5、如果存在与 bean 关联的任何BeanPostProcessors,则调用 preProcessBeforeInitialization() 方法。
- 6、如果为 bean 指定了 init 方法(
<bean>
的 init-method 属性),那么将调用它。 - 7、最后,如果存在与 bean 关联的任何 BeanPostProcessors,则将调用 postProcessAfterInitialization() 方法。
- 8、如果 bean 实现DisposableBean 接口,当 spring 容器关闭时,会调用 destory()。
- 9、如果为bean 指定了 destroy 方法(
<bean>
的 destroy-method 属性),那么将调用它。
14、什么是 spring 的内部 bean?
- 只有将 bean 用作另一个 bean 的属性时,才能将 bean 声明为内部 bean。为了定义 bean,Spring 的基于 XML 的配置元数据在
<property>
或<constructor-arg>
中提供了 元素的使用。内部 bean 总是匿名的,它们总是作为原型。
例如,假设我们有一个 Student 类,其中引用了 Person 类。这里我们将只创建一个 Person 类实例并在 Student 中使用它。
java
public class Student {
private Person person;
//Setters and Getters
}
public class Person {
private String name;
private String address;
//Setters and Getters
}
xml
<bean id="StudentBean" class="com.edureka.Student">
<property name="person">
<!--This is inner bean-->
<bean class="com.edureka.Person">
<property name="name" value="Scott"></property>
<property name="address" value="Bangalore"></property>
</bean>
</property>
</bean>
15、什么是 spring 装配
- 当 bean 在 Spring 容器中组合在一起时,它被称为装配或 bean 装配。Spring容器需要知道需要什么 bean 以及容器应该如何使用依赖注入来将 bean 绑定在一起,同时装配 bean。
- 在 Spring 中,装配(Assembly)指的是将应用程序的各个组件(例如 bean、依赖项等)组合在一起的过程。Spring 提供了多种装配机制,以便将应用程序中的组件连接起来,实现依赖注入和控制反转。
16、spring的装配方式有哪些?
- XML 装配 :通过 XML 配置文件来定义 bean 以及它们之间的依赖关系。使用
<bean>
标签定义 bean,并使用<property>
标签或者构造函数参数来注入依赖。 - 注解装配:使用注解来标识组件,Spring 根据注解信息自动完成装配。常见的注解包括 @Component、@Autowired、@Service、@Repository 等。
- Java 配置类装配 :通过 Java 配置类来定义 bean 和依赖关系。使用
@Configuration
注解标识配置类,然后使用@Bean
注解定义 bean,通过方法返回 bean 实例,也可以使用@Autowired
注解注入其他 bean。 - 自动装配 :Spring 提供了自动装配功能,根据类型或者名称自动将依赖注入到 bean 中。可以通过在 bean 的属性上标注
@Autowired
注解来实现自动装配。 - Java EE 和 JNDI 注入:Spring 支持从 Java EE 环境和 JNDI 上下文中获取资源,并将其注入到 Spring 管理的 bean 中。
- Spring 的装配机制使得组件之间的依赖关系变得松耦合,提高了应用程序的灵活性和可维护性。开发人员可以根据项目的需求选择合适的装配方式来构建应用程序。
17、spring自动装配有哪些方式?
- Spring 容器能够自动装配 bean。也就是说,可以通过检查 BeanFactory 的内容让 Spring 自动解析 bean 的协作者。
- 自动装配的不同模式:
- no(不启用): 这是默认设置,表示没有自动装配。应使用显式 bean 引用进行装配。
- byName(按名称)-:它根据 bean 的名称注入对象依赖项。它匹配并装配其属性与 XML文件中由相同名称定义的 bean。
- byType(按类型)-:它根据类型注入对象依赖项。如果属性的类型与 XML 文件中的一个 bean 名称匹配,则匹配并装配属性。
- 构造函数(按构造方法)-:它通过调用类的构造函数来注入依赖项。它有大量的参数。
- autodetect: 首先容器尝试通过构造函数使用 autowire 装配,如果不能,则尝试通过 byType 自动装配。
PS:
- 在 Spring 中,autodetect 是一种自动检测机制,用于自动发现并注册 Spring bean。通常,Spring 容器需要明确地知道哪些类应该被实例化为 bean,以及它们之间的依赖关系。但是,当你在 Spring 的配置文件中使用 autodetect 时,Spring 将会自动扫描指定的包或类路径,然后将符合条件的类自动注册为 bean。
- 具体来说,autodetect 可以在 XML 配置文件中的
<context:component-scan>
元素中使用。这个元素告诉 Spring 应该扫描哪些包来自动注册 bean。
xml
<context:component-scan base-package="com.example.beans" />
在这个示例中,Spring 将会扫描 com.example.beans 包及其子包下的所有类,并将符合条件的类注册为 bean。
-
默认情况下,Spring 使用的是 @Component 及其衍生注解(如 @Repository、@Service、@Controller 等)来标识候选 bean 类。如果某个类被标注了这些注解,并且它被扫描到了,那么 Spring 就会将其注册为一个 bean。
-
这种自动检测机制减少了手动配置的工作,特别是在大型项目中,可以显著简化配置文件的编写,提高开发效率。但需要注意,自动检测需要谨慎使用,以避免注册不必要的类或出现意外的行为。
18、自动装配有什么局限?
- 被覆盖的可能性 :您始终可以使用
<constructor-arg>
和<property>
设置指定依赖项,这将覆盖自动装配。 - 基本元数据类型:简单属性(如原数据类型,字符串和类)无法自动装配。
- 令人困惑的性质:总是喜欢使用明确的装配,因为自动装配不太精确
19、Spring框架中都用到了哪些设计模式?
- 不仅要回设计模式,还要知道每个设计模式在Spring中是如何使用
的。
- 简单工厂模式 :Spring 中的 BeanFactory 就是简单工厂模式的体现。根据传入一个唯一的标识来获得 Bean 对象,但是在传入参数后创建还是传入参数前创建,要根据具体情况来定。
- 工厂模式:Spring 中的 FactoryBean 就是典型的工厂方法模式,实现了 FactoryBean 接口的 bean是一类叫做 factory 的 bean。其特点是,spring 在使用 getBean() 调用获得该 bean 时,会自动调用该 bean 的 getObject() 方法,所以返回的不是 factory 这个 bean,而是这个 bean.getOjbect()方法的返回值。
- 单例模式:在 spring 中用到的单例模式有:scope="singleton" ,注册式单例模式,bean 存放于Map 中。bean name 当做 key,bean 当做 value。
- 代理模式(Proxy Pattern):Spring AOP(面向切面编程)功能的核心就是代理模式。Spring 使用代理对象来在目标方法执行前后执行增强逻辑。
- 原型模式:在 spring 中用到的原型模式有:scope="prototype" ,每次获取的是通过克隆生成的新实例,对其进行修改时对原有实例对象不造成任何影响。
- 迭代器模式:在 Spring 中有个 CompositeIterator 实现了 Iterator,Iterable 接口和 Iterator 接口,这两个都是迭代相关的接口。可以这么认为,实现了 Iterable 接口,则表示某个对象是可被迭代的。Iterator 接口相当于是一个迭代器,实现了Iterator 接口,等于具体定义了这个可被迭代的对象时如何进行迭代的。
- 代理模式:Spring 中经典的 AOP,就是使用动态代理实现的,分 JDK 和 CGlib 动态代理。
- 适配器模式:Spring 中的 AOP 中 AdvisorAdapter 类,它有三个实现:MethodBeforAdviceAdapter、AfterReturnningAdviceAdapter、ThrowsAdviceAdapter。Spring会根据不同的 AOP 配置来使用对应的 Advice,与策略模式不同的是,一个方法可以同时拥有多个Advice。Spring 存在很多以 Adapter 结尾的,大多数都是适配器模式。
- 观察者模式 :Spring 中的 Event 和 Listener。spring 事件:ApplicationEvent,该抽象类继承了EventObject 类,JDK 建议所有的事件都应该继承自 EventObject。
- spring 事件监听器:ApplicationListener,该接口继承了 EventListener 接口,JDK 建议所有的事件监听器都应该继承
EventListener。
- spring 事件监听器:ApplicationListener,该接口继承了 EventListener 接口,JDK 建议所有的事件监听器都应该继承
- 模板模式:Spring 中的 org.springframework.jdbc.core.JdbcTemplate 就是非常经典的模板模式的应用,里面的 execute 方法,把整个算法步骤都定义好了。
- 责任链模式:DispatcherServlet 中的 doDispatch() 方法中获取与请求匹配的处理器HandlerExecutionChain、this.getHandler() 方法的处理使用到了责任链模式。
- 依赖注入(Dependency Injection):虽然不是传统意义上的设计模式,但依赖注入是 Spring 的核心特性之一,通过反转控制来管理对象之间的依赖关系。
- 装饰者模式(Decorator Pattern):Spring 中的 BeanPostProcessor 接口允许开发者在 bean 初始化过程中添加额外的逻辑,这类似于装饰者模式,可以动态地为 bean 添加功能。
- 策略模式(Strategy Pattern):Spring 的资源抽象层(Resource Abstraction)中使用了策略模式,不同的资源加载器(如 UrlResource、ClassPathResource 等)根据不同的策略加载资源。
- 注意:这里只是列举了部分设计模式,其实里面用到了还有享元模式、建造者模式等等。
20、、Spring 框架中的单例 Bean 是线程安全的么?
- Spring 框架并没有对单例 Bean 进行任何多线程的封装处理。
- 关于单例 Bean 的线程安全和并发问题,需要开发者自行去搞定。
- 单例的线程安全问题,并不是 Spring 应该去关心的。Spring 应该做的是,提供根据配置,创建单例 Bean 或多例 Bean 的功能。
- 当然,但实际上,大部分的 Spring Bean 并没有可变的状态,所以在某种程度上说 Spring 的单例Bean 是线程安全的。如果你的 Bean 有多种状态的话,就需要自行保证线程安全。最浅显的解决办法,就是控制多态 Bean 的作用域(Scope)设置为 Singleton 或者 Prototype。