Springでの@DependsOnアノテーションの機能と実装の原則

Springでの@DependsOnアノテーションの機能と実装の原則

公式文書説明

Beans on which the current bean depends. Any beans specified are guaranteed to be created by the container before this bean. Used infrequently in cases where a bean does not explicitly depend on another through properties or constructor arguments, but rather depends on the side effects of another bean's initialization.
A depends-on declaration can specify both an initialization-time dependency and, in the case of singleton beans only, a corresponding destruction-time dependency. Dependent beans that define a depends-on relationship with a given bean are destroyed first, prior to the given bean itself being destroyed. Thus, a depends-on declaration can also control shutdown order.
May be used on any class directly or indirectly annotated with org.springframework.stereotype.Component or on methods annotated with Bean.
Using DependsOn at the class level has no effect unless component-scanning is being used. If a DependsOn-annotated class is declared via XML, DependsOn annotation metadata is ignored, and <bean depends-on="..."/> is respected instead.

@DependsOnアノテーションの役割

org.springframework.context.annotation.DependsOn
アノテーションの属性は文字列の配列であり、配列の要素は各依存Beanの名前です。

@Target({
    
    ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DependsOn {
    
    

	String[] value() default {
    
    };

}

@DependsOnアノテーションは主に、現在のBeanが依存するBeanを指定するために使用されます。依存関係として指定されたBeanは、Springによって現在のBeanの前に作成されることが保証されています。場合によっては、Beanがプロパティまたはコンストラクターパラメーターを介して別のBeanに明示的に依存しないが、最初に別のBeanを初期化する必要がある場合は、@DependsOnこのアノテーションを使用できます

@DependsOnいずれかの初期化依存順序を指定することができ、または対応するの破壊実行順序ビーンを指定することができる(のみシングルトンビーンの場合)。

直接または間接的に@Component、または@Bean注釈付きのメソッド注釈が付けられているBeanに使用できます
xml構成を使用している場合は、<bean dependens on=“…”/>タグを使用する必要があります。

簡単な説明は@DependsOn、Beanの作成、初期化(InitializingBean)、および破棄メソッドの実行順序を制御できることです

例:次の2つのインターフェースをそれぞれ実装するAaa、Bbb、およびCccという3つのBeanクラスがあるとします。
org.springframework.beans.factory.InitializingBean
org.springframework.beans.factory.DisposableBean

Cccは、@ DependsOnを介した依存Beanの作成順序をBbb> Aaaとして指定します。

@DependsOn({
    
    "bbb","ccc"})
@Service
public class Aaa implements InitializingBean, DisposableBean {
    
    
    private static final Logger logger = LoggerFactory.getLogger(Aaa.class);

    public Aaa() {
    
    
        logger.info(this.getClass().getName() + " Construction");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    
    
        logger.info(this.getClass().getName() + " afterPropertiesSet");
    }

    @Override
    public void destroy() throws Exception {
    
    
        logger.info(this.getClass().getName() + " destroy");
    }
}

BbbCccクラスは次のように実装されます

@Service
public class Bbb implements InitializingBean, DisposableBean {
    
    
    //实现和Aaa相同
}
@Service
public class Ccc implements InitializingBean, DisposableBean {
    
    
    //实现和Aaa相同
}

その場合、最初の順序は次のようになります。bbb --> ccc --> aaa
ここに画像の説明を挿入します
破棄メソッドの実行順序は次のように正反対です。aaa --> ccc --> bbb
ここに画像の説明を挿入します

@DependsOnアノテーションの実現原理

Springが起動時にBeanをスキャンすると、BeanDefinitionにカプセル化されます。そうである場合AnnotatedBeanDefinition、クラスのアノテーション情報が解析され、アノテーションが検出され@DependsOn、値の値が読み取られ、BeanDefinition#setDependsOn保存が呼び出されます。
ソースコードを参照してくださいClassPathBeanDefinitionScanner#doScanAnnotationConfigUtils#processCommonDefinitionAnnotations(AnnotatedBeanDefinition, AnnotatedTypeMetadata)

Beanが作成されるとき、つまり呼び出されるAbstractBeanFactory#doGetBeanと、依存BeanNameが取得されAbstractBeanFactory#getBean(beanName)依存関係の順序を制御するために、配列の順序で依存Beanの作成を優先するために呼び出されます。

さらに、Beanが作成されるとAbstractBeanFactory#registerDisposableBeanIfNecessary、SpringのDefaultSingletonBeanRegistry#registerDisposableBeandestroyメソッドにBeanを登録するためにも呼び出されます。ソースコード参照し、LinkedHashMapを介して内部に保存します。キーはBean名です。プロセスが終了すると、破棄メソッドが逆の順序で呼び出されます。
ソースコードを見るDefaultSingletonBeanRegistry#destroySingletons

public void destroySingletons() {
    
    
	if (logger.isTraceEnabled()) {
    
    
		logger.trace("Destroying singletons in " + this);
	}
	synchronized (this.singletonObjects) {
    
    
		this.singletonsCurrentlyInDestruction = true;
	}

	String[] disposableBeanNames;
	synchronized (this.disposableBeans) {
    
    
		disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
	}
	for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
    
    
		destroySingleton(disposableBeanNames[i]);
	}

	this.containedBeanMap.clear();
	this.dependentBeanMap.clear();
	this.dependenciesForBeanMap.clear();

	clearSingletonCache();
}

今日は大晦日に皆さん、明けましておめでとうございます!大金を稼ぎます!

おすすめ

転載: blog.csdn.net/u013202238/article/details/113360497