ApplicationContextAwareはSpringでどのように機能しますか?


82

春に、Beanが実装する場合、BeanはにApplicationContextAwareアクセスできますapplicationContext。したがって、他のBeanを取得できます。例えば

public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;     

    public void setApplicationContext(ApplicationContext context) throws BeansException {
      applicationContext = context;
    }

    public static ApplicationContext getApplicationContext() {
      return applicationContext;
    }
}

次にSpringContextUtil.getApplicationContext.getBean("name")、Beanの「名前」を取得できます。

これを行うSpringContextUtilにはapplications.xml、これを内部に配置する必要があります。

<bean class="com.util.SpringContextUtil" />

ここでは、BeanSpringContextUtilにプロパティは含まれていませんapplicationContext。Spring Beanが初期化されると、このプロパティが設定されると思います。しかし、これはどのように行われますか?メソッドはどのようsetApplicationContextに呼び出されますか?


12
春は魔法です。魔法を
受け入れる

回答:


98

春の豆をインスタンス化するとき、それはのようなインターフェースのカップルを探しますApplicationContextAwareInitializingBean。それらが見つかった場合、メソッドが呼び出されます。例(非常に簡略化)

Class<?> beanClass = beanDefinition.getClass();
Object bean = beanClass.newInstance();
if (bean instanceof ApplicationContextAware) {
    ((ApplicationContextAware) bean).setApplicationContext(ctx);
}

新しいバージョンでは、Spring固有のインターフェイスを実装するよりも、アノテーションを使用する方がよい場合があることに注意してください。今、あなたは単に使うことができます:

@Inject // or @Autowired
private ApplicationContext ctx;

4
どうもありがとうございました、これが私が欲しいものです!たぶん私は春がどのように機能するかを理解するためにいくつかの春のコードを読む必要があります。
ジミー

2
ほとんどの場合は@Autowiredを使用することをお勧めしますが、それが機能しない場合もあります。たとえば、シングルトンの「@Component」があるが、セッションスコープを持つBeanを注入する必要がある場合などです。依存関係はアプリケーションコンテキストの作成時に自動配線されるため、実際にはセッションBeanが挿入されることはありません。アプリケーションコンテキストへの参照があると、プログラムでセッションBeanを取得でき、セッションBeanインスタンスが正しく返されます。
raspacorp 2014

Springは代わりに動的に生成されたプロキシクラスを挿入することを期待します-そのようなクラスはアプリケーションスコープを持っていますが、アクセスされると、セッションスコープインスタンスに委任するか、現在実行中のスレッドにバインドされたリクエストがない場合は例外をスローします
xorcus

@raspacorp sessonスコープBeanを注入ApplicationContextから取得できない場合は、ApplicationContextAware instanceどちらからも取得できません。注入されたものApplicationContextAware instanceと同じapplicationContextオブジェクトからBeanを取得するためです。
ティイナ2018年

10

Inクラス
を使用するときにApplicationContextAwareがどのように機能するかを説明するSpringソースコード。メソッドには次のコードがあります。 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
AbstractApplicationContextrefresh()

// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

このメソッドを入力beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));すると、ApplicationContextAwareProcessorがAbstractrBeanFactoryに追加されます。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
        // Configure the bean factory with context callbacks.
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
...........

春にBeanを初期化するときAbstractAutowireCapableBeanFactory、メソッドinitializeBeanapplyBeanPostProcessorsBeforeInitialization、Beanのポストプロセスを実装するために呼び出します。プロセスには、applicationContextの注入が含まれます。

@Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessBeforeInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }

BeanPostProcessorがObjectを実装して、たとえばApplicationContextAwareProcessor前に追加したpostProcessBeforeInitializationメソッドを実行する場合。

private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
                        new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

0

実行されるApplicationContextの通知を希望するオブジェクトによって実装されるインターフェース。

上記は、SpringドキュメントのWebサイトhttps://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContextAware.htmlから抜粋したものです。

そのため、Springコンテナが起動したときに何かを実行したい場合は、そのときに呼び出されたようです。

コンテキストを設定する方法は1つしかないので、コンテキストを取得して、すでにコンテキスト内にある何かを実行すると思います。


-1

ApplicationContextAwareインターフェイス、現在のアプリケーションコンテキスト。これを介して、Springコンテナサービスを呼び出すことができます。クラスの以下のメソッドによって注入された現在のapplicationContextインスタンスを取得できます

public void setApplicationContext(ApplicationContext context) throws BeansException.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.