Spring依赖属性和@DependsOn注释
如果一个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首先被初始化。