Bean

Spring Bean是由Spring IoC容器管理的对象实例,也是Spring框架的基本组件之一。

Bean可以是任何一个普通的Java对象,也可以是第三方库中的对象,例如Hibernate SessionFactoryMyBatis SqlSessionFactory

Spring Bean的创建、组装和管理是由Spring IoC容器负责的。在容器中注册一个Bean后,容器负责创建Bean的实例、管理Bean的生命周期,以及处理Bean之间的依赖关系。通过 Spring 容器,可以实现对象之间的松耦合,便于测试、模块化开发、重用等。

Spring中,Bean是通过配置文件或注解来定义的。 配置文件通常是XMLJava配置类,通过声明Bean的类名、作用域、依赖关系、属性值等信息来定义Bean。 注解则是通过在Bean类上添加特定的注解来定义Bean。 无论是XML配置文件还是注解,都需要被Spring IoC容器加载和解析,以创建Bean的实例并放入容器中。

@Component

在运行时,Spring会找到所有使用@Component或其派生类进行注释的类,并将它们用作bean定义。 查找带注释的类的过程称为组件扫描。

@Conpontent衍生物是Spring构造型注释,它们本身用@Component注释。

@Component衍生列表包括:

  • @Service
  • @Repository
  • @Controller

注释之间的区别纯粹是信息性的。它们允许你根据通用职责轻松对bean进行分类。 你可以使用这些注释将bean类标记为特定应用程序层的成员,Spring框架会将它们全部视为@Components

Bean的作用域

SpringBean的作用域通常有:

  • singleton:单例,这种bean范围是默认的,这种范围确保不管接受到多少个请求,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。
  • prototype:原形,范围与单例范围相反,每次获取都会创建一个新的bean实例,连续getBean()两次,是不同的Bean实例。
  • request(Web应用使用):请求,在请求bean范围内会每一个来自客户端的网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收
  • session(Web应用使用):会话,与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
  • application/global-session(Web应用使用):全局会话,在一个全局的Http Session中,容器会返回该bean的同一个实例,仅在使用portlet context时有效。
  • websocket(Web应用使用):网络通信,在WebSocket会话范围内会创建一个新的bean

Bean的生命周期

Spring上下文中的Bean生命周期如下:

  • 实例化Bean
    • 对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。
    • 对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean
  • 设置对象属性(依赖注入):实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息以及通过BeanWrapper提供的设置属性的接口完成依赖注入。
  • 处理Aware接口:
    • Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean
      • 如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的就是Spring配置文件中Beanid值;
      • 如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,传递的是Spring工厂自身。
      • 如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文;
  • BeanPostProcessor:如果想对Bean进行一些自定义的处理,那么可以让Bean实现了BeanPostProcessor接口,那将会调用postProcessBeforeInitialization(Object obj, String s)方法。
  • InitializingBeaninit-method
    • 如果BeanSpring配置文件中配置了init-method属性,则会自动调用其配置的初始化方法。
    • 如果这个Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法; 由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术

以上几个步骤完成后,Bean就已经被正确创建了,之后就可以使用这个Bean了。

  • DisposableBean:当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;
  • destroy-method:如果这个BeanSpring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。

Bean注入的实现方式

早期的开发基本是基于xml的配置,目前大部分都是基于注解的配置

基于xml注入bean

构造器注入

/*带参数,方便利用构造器进行注入*/
public ADaoImpl(String msg){
    this.msg = msg;
}

xml配置

<bean id="ADaoImpl" class="com.ADaoImpl">
    <constructor-arg value="msg"></constructor-arg>
</bean>

setter方法注入

public class AId {
    private int id;
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
}

xml配置

<bean id="AId" class="com.AId">
    <property name="id" value="111"></property>
</bean>

静态工厂注入

静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象,为了让spring管理所有对象, 我们不能直接通过工程类.静态方法()来获取对象,而是依然通过spring注入的形式获取:

public class DaoFactory { //静态工厂
    public static final FactoryDao getStaticFactoryDaoImpl(){
        return new StaticFacotryDaoImpl();
    }
}
public class SpringAction {
    private FactoryDao staticFactoryDao; //注入对象
    //注入对象的 set 方法
    public void setStaticFactoryDao(FactoryDao staticFactoryDao) {
        this.staticFactoryDao = staticFactoryDao;
    }
}

xml配置

<!--factory-method="getStaticFactoryDaoImpl"指定调用哪个工厂方法-->
<bean name="springAction" class=" SpringAction" >
    <!--使用静态工厂的方法注入对象,对应下面的配置文件-->
    <property name="staticFactoryDao" ref="staticFactoryDao"></property>
</bean>

<!--此处获取对象的方式是从工厂类中获取静态方法-->
<bean name="staticFactoryDao" class="DaoFactory" 
      factory-method="getStaticFactoryDaoImpl"></bean>

实例工厂

实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先new工厂类,再调用普通的实例方法:

 public class DaoFactory { //实例工厂 
    public FactoryDao getFactoryDaoImpl(){
        return new FactoryDaoImpl();
    }
}
public class SpringAction {
    private FactoryDao factoryDao; //注入对象 
    public void setFactoryDao(FactoryDao factoryDao) {
        this.factoryDao = factoryDao;
    }
}

xml配置

<bean name="springAction" class="SpringAction">
    <!--使用实例工厂的方法注入对象,对应下面的配置文件-->
    <property name="factoryDao" ref="factoryDao"></property>
</bean>

<!--此处获取对象的方式是从工厂类中获取实例方法-->
<bean name="daoFactory" class="com.DaoFactory"></bean>
<bean name="factoryDao" factory-bean="daoFactory"
      factory-method="getFactoryDaoImpl"></bean>

基于注解注入bean

声明bean

  • @Component:通用的注解,可标注任意类为Spring组件。如果一个Bean不清楚属于哪一层,可以使用@Component注解标注。
  • @Repository: 对应持久层即Dao层,主要用于数据库相关操作。
  • @Service: 对应服务层,主要涉及一些复杂的逻辑,需要用到Dao层。
  • @Controller: 对应Spring MVC控制层,主要用户接受用户请求并调用Service层返回数据给前端。
@Component@Bean的区别
  • @Component注解作用于类,而@Bean注解作用于方法。
  • @Component通常是通过类路径扫描来⾃动侦测以及⾃动装配到Spring容器中(我们可以使用 @ComponentScan注解定义要扫描的路径从中找出标识了需要装配的类⾃动装配到Springbean容器中)。 @Bean注解通常是我们在标有该注解的方法中定义产生这个bean, @Bean告诉了Spring这是某个类的实例,当我需要用它的时候还给我。
  • @Bean注解比@Component注解的⾃定义性更强,而且很多地方我们只能通过@Bean注解来注册bean。 比如当我们引用第三方库中的类需要装配到Spring容器时,则只能通过@Bean来实现。

使用Bean

Spring内置的@Autowired以及JDK内置的@Resource@Inject都可以⽤于注入Bean

一般都是使用@Autowired@Resource

@Autowired@Resource的区别

5种不同方式的自动装配

Spring装配包括手动装配和自动装配,手动装配是有基于xml装配、构造方法、setter方法等

自动装配有五种自动装配的方式,可以用来指导Spring容器用自动装配方式来进行依赖注入。

  1. no:默认的方式是不进行自动装配,通过显式设置ref属性来进行装配。
  2. byName:通过参数名自动装配,Spring容器在配置文件中发现beanautowire属性被设 置成byName,之后容器试图匹配、装配和该bean的属性具有相同名字的bean
  3. byType:通过参数类型自动装配,Spring容器在配置文件中发现beanautowire属性被 设置成byType,之后容器试图匹配、装配和该bean的属性具有相同类型的bean。如果有多个bean符合条件,则抛出错误。
  4. constructor:这个方式类似于byType,但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
  5. autodetect:首先尝试使用constructor来自动装配,如果无法工作,则使用byType方式。

results matching ""

    No results matching ""