1、Spring的Bean和我们创建的对象有什么区别?
Spring的Bean和我们自己创建的对象在以下几个方面有区别:
管理方式: Spring的Bean由Spring容器进行管理,而我们自己创建的对象是由我们自己来管理。Spring容器负责创建、初始化、配置、销毁和依赖注入等管理工作。
生命周期:Spring的Bean有生命周期管理。在创建Bean时,Spring容器会调用构造函数或工厂方法来实例化Bean对象。然后,它会应用各种配置和初始化操作,例如依赖注入和初始化回调。当容器关闭时,Spring会销毁这些Bean,并调用销毁回调方法。
依赖注入:Spring的Bean可以通过依赖注入来解决对象之间的依赖关系。Spring容器负责将依赖关系自动注入到Bean中,而我们自己创建的对象需要手动管理它们之间的依赖关系。
AOP(面向切面编程):Spring的Bean支持AOP功能。通过配置切面和通知,可以在Bean的方法执行前、后或异常发生时添加额外的逻辑。我们自己创建的对象没有内置的AOP支持,需要手动实现和管理。
可配置性:通过注解或XML配置,我们可以在Spring中对Bean进行更灵活的配置。我们可以定义不同的配置文件,根据需要选择不同的配置,或在运行时动态调整配置。而我们自己创建的对象的配置通常是静态的,并且与代码紧密耦合。
总的来说,Spring的Bean相对于我们自己创建的对象具有更高的灵活性、可配置性和管理能力,通过Spring容器来管理和协调Bean对象,使我们能够更好地组织和管理应用程序的组件。
2、Spring容器返回的都是代理对象吗?
不是所有情况下Spring容器都会返回代理对象。具体是否返回代理对象取决于配置和使用的方式。
Spring容器会根据@Bean注解或XML配置文件中的定义,实例化和管理Bean对象。通常情况下,如果目标Bean被声明为被代理的,例如通过事务管理或AOP功能,则Spring容器会返回代理对象。这主要涉及以下两种情况:
基于接口的代理:如果目标Bean实现了至少一个接口,并且配置启用了接口代理(默认情况下是启用的),Spring会使用JDK动态代理来创建代理对象,并返回该代理对象。
基于类的代理:如果目标Bean没有实现接口或配置要求使用基于类的代理,Spring会使用CGLIB来创建代理对象,并返回该代理对象。
然而,如果目标Bean没有被声明为被代理的,或者没有配置任何切面或增强逻辑,Spring容器将直接返回原始的目标Bean对象,而非代理对象。
总之,Spring容器返回代理对象的前提是目标Bean被声明为被代理的,并配置了相应的切面或增强逻辑。否则,Spring容器会直接返回原始的目标Bean对象。
经过AOP增强的,Spring容器返回的是代理对象,反之则是普通bean对象
3、spring单例bean和原型bean的区别?
1、spring的单例bean和多例bean的销毁不一样
对于单例bean,Spring容器会在容器关闭时自动销毁它们。这是因为单例bean是全局共享的,当容器关闭时,所有的单例bean都会被销毁。你可以通过在bean的类中实现DisposableBean接口或添加@PreDestroy注解来定义销毁方法,Spring容器会在销毁时调用该方法。对于多例bean,Spring容器不会跟踪和销毁它们。多例bean的生命周期由调用者负责管理。你可以在定义多例bean时实现自己的销毁逻辑,通过调用ApplicationContext的getBean()方法来获取多例bean的实例,并手动调用销毁方法。当容器关闭时,多例bean的引用会被释放,但并不意味着它们被自动销毁。多例bean可能仍然存在于内存中,直到被Java的垃圾回收机制清理为止。
2、单例bean线程不安全,原型bean线程安全
单例是不安全的:
Spring容器在初始化bean时,会为其创建一个单例实例,这个实例在整个应用中是唯一的,并且只会被初始化一次。由于这个特性,bean在默认情况下不是线程安全的。
多例(原型)是安全的:
每个bean实例都是独立的,因此为防止并发问题出现时,当一个请求改变了对象状态,此时对象又处理另一个请求时,导致对后者的请求作出了错误响应。所以使用多例bean,因为是线程安全的。
4、spring单例bean销毁是清空单例池吗?
在Spring中,单例bean的销毁过程并不是简单地清空单例池。
在容器关闭时,Spring会触发单例bean的销毁过程。首先,它会依次销毁所有的单例bean,调用每个单例bean的销毁回调方法。这些销毁回调方法可以通过实现
DisposableBean
接口的destroy()
方法或者使用@PreDestroy
注解来定义。在销毁过程中,Spring会调用每个单例bean的销毁方法来释放它们所持有的资源,例如关闭数据库连接、释放文件句柄等。这些销毁方法的具体实现由开发者自行定义。
当所有的单例bean都被销毁后,Spring容器会继续执行其他的关闭操作,最终关闭容器。在容器关闭后,单例池的状态将被清空,但在单例池关闭之前,单例bean的销毁过程会涉及到一系列的资源释放和清理操作。
总结起来,单例bean的销毁过程并不仅仅是简单地清空单例池,而是涉及到对每个单例bean的销毁回调方法的调用以及释放持有的资源。
5、spring依赖注入的6个判断
在Spring依赖注入中,有以下6个判断条件来确定注入哪个Bean:
类型匹配(Type matching): Spring会根据被注入属性的类型来匹配合适的Bean进行注入,要求被注入属性的类型必须与Bean的类型匹配或兼容。
名称匹配(Name matching): 如果类型匹配有多个候选Bean时,Spring会根据被注入属性的名称与Bean的名称进行匹配,只有名称匹配的Bean才会被注入。
唯一性(Uniqueness): 如果通过类型匹配和名称匹配都没有找到唯一的Bean,那么Spring会尝试判断是否有一个Bean定义了
@Primary
注解,如果有,则注入该Bean;如果没有找到唯一的Bean或者@Primary
注解,则会抛出异常。限定符(Qualifier): 当存在多个候选Bean时,可以使用
@Qualifier
注解来指定要注入的Bean的限定符(Qualifier),限定符是一个自定义的标识符,用于在多个Bean中进行更精确的匹配。注解匹配(Annotation matching): 可以使用自定义注解来标注Bean,并使用
@Autowired
注解的@Qualifier
属性进行匹配。例如,可以定义一个自定义注解@MyCustomAnnotation
,然后使用@Autowired
注解的@Qualifier
属性指定@MyCustomAnnotation
进行匹配。高级选择(Advanced selection): Spring还提供了更高级的选择方式,如使用Spring表达式语言(SpEL)、使用自定义的注解、自定义的选择器接口等方式来选择要注入的Bean。
综上所述,Spring依赖注入根据类型匹配、名称匹配、唯一性、限定符、注解匹配和高级选择等6个判断条件来决定注入哪个Bean。这些条件可以组合使用,以实现更精确的注入控制。
Spring的@Autowired是先ByType后ByName,而Java EE提供的@Resource注解是先ByName,再ByType