Spring依赖属性和@DependsOn注释

时间:2020-01-09 10:44:34  来源:igfitidea点击:

如果一个bean依赖于另一个bean,那么通常在Spring框架中,我们会将其配置为另一个bean的属性。通常,我们可以使用基于XML的配置元数据中的<ref />元素或者使用@Autowired注释来完成此操作。但是,有时bean之间的依赖关系可能不是直接的,但我们可能仍要确保在另一个bean之前初始化特定的bean。例如,在一个bean中,有一个静态块必须在初始化另一个bean之前执行。在Spring中,可以在XML配置中使用@ on-on属性或者@DependsOn注释在使用此元素的bean初始化之前显式强制初始化一个或者多个bean。

Spring依赖属性示例

在该示例中,有一个ClassB类和另一个具有静态块的ClassA类。我们要确保ClassA首先被初始化,并且在初始化ClassB之前要执行它的静态块,即使ClassB与ClassA没有直接依赖也是如此。

public class ClassA {
  ClassA(){
    System.out.println("In constructor of ClassA");
  }
  //static block
  static {
    System.out.println("in static block ClassA");
    System.out.println("Register DB Driver as a one time activity");
  }
}
public class ClassB {
  ClassB(){
    System.out.println("In constructor of ClassB");
  }
}

组态

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="beanA" class="com.theitroad.springbeans.ClassA" />  
   	
    <bean id="beanB" class="com.theitroad.springbeans.ClassB" depends-on="beanA">  
    </bean>
</beans>

在配置中,有一个ClassA和ClassB的bean定义,如我们所见,beanB中没有对beanA的直接依赖关系,因此depends-on属性用于强制在beanB之前初始化beanA。

我们可以将以下类与main方法一起使用以读取配置并访问bean。

public class App {
  public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
    ClassB obj = context.getBean("beanB", ClassB.class);
    context.close();
  }
}

输出:

10:26:02.631 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanA'
in static block ClassA
Register DB Driver as a one time activity
In constructor of ClassA
10:26:02.683 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanB'
In constructor of ClassB

从输出中可以看到,beanA首先被初始化。

对多个bean使用依赖

如果对多个bean有依赖关系,请提供一个bean名称列表作为depends-on属性的值(逗号,空格和分号是有效的分隔符)。

<bean id="beanA" class="com.theitroad.springbeans.ClassA" />  
<bean id="beanB" class="com.theitroad.springbeans.ClassB" />
<bean id="beanC" class="com.theitroad.springbeans.ClassC" depends-on="beanA,beanB">  
</bean>

Spring @DependsOn注释示例

如果我们正在使用Spring Java配置或者注释来扫描组件,则可以在Spring中使用@DependsOn注释来显式强制首先初始化一个或者多个bean。此注释可以直接在任何类上使用,也可以间接用Component注释,或者用Bean注释的方法间接使用。

下面的示例显示了@DependsOn注释的使用,其中使用了Spring Java配置,因此@DependsOn注释与@Bean注释一起使用。

public class ClassA {
  public ClassA(){
    System.out.println("In constructor of ClassA");
  }
  //static block
  static {
    System.out.println("in static block ClassA");
    System.out.println("Register DB Driver as a one time activity");
  }
}
public class ClassB {
  public ClassB(){
    System.out.println("In constructor of ClassB");
  }
}
public class ClassC {
  public ClassC(){
    System.out.println("In constructor of ClassC");
  }
}

Java配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import com.theitroad.springbeans.ClassA;
import com.theitroad.springbeans.ClassB;
import com.theitroad.springbeans.ClassC;

@Configuration
public class AppConfig {
  @Bean
  @DependsOn({"beanA","beanB"})
  public ClassC beanC() {
    return new ClassC();
  }
  @Bean
  public ClassB beanB() {
    return new ClassB();
  }
  @Bean
  public ClassA beanA() {
    return new ClassA();
  }
}

在配置中,有一个ClassA,ClassB和ClassC的bean定义。为了强制在beanC之前初始化beanA和beanB,在ClassC的bean定义上使用@DependsOn注释,并将beanA和beanB作为值。

为了运行该应用程序,我们可以使用以下类。

public class App {

  public static void main(String[] args) {
    AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    ClassC obj = context.getBean("beanC", ClassC.class);
    context.close();
  }
}

输出:

10:52:01.160 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanA'
in static block ClassA
Register DB Driver as a one time activity
In constructor of ClassA
10:52:01.293 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanB'
In constructor of ClassB
10:52:01.297 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanC'
In constructor of ClassC

从输出中可以看到,beanA和beanB首先被初始化。