ApplicationContextAware Spring'de nasıl çalışır?


82

İlkbaharda, bir fasulye uygularsa ApplicationContextAware, o zaman applicationContext. Bu nedenle diğer fasulyeleri alabilmektedir. Örneğin

public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;     

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

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

Sonra SpringContextUtil.getApplicationContext.getBean("name")fasulyenin "adını" alabilir.

Bunu yapmak için, biz bu koymalıyız SpringContextUtiliçeride applications.xml, örneğin

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

Fasulye SpringContextUtilmülkü içermiyor applicationContext. Sanırım bahar fasulyesi başladığında bu özellik ayarlanır. Ama bu nasıl yapılır? Yöntem nasıl setApplicationContextçağrılır?


13
Bahar Sihirlidir. Sihri kucakla
Rosenthal

Yanıtlar:


99

Bahar fasulyeleri örneklediğinde, ApplicationContextAwareve gibi birkaç arayüz arar InitializingBean. Bulunurlarsa, yöntemler çağrılır. Örneğin (çok basitleştirilmiş)

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

Daha yeni sürümde, yaya özgü arayüzler uygulamak yerine ek açıklamaları kullanmanın daha iyi olabileceğini unutmayın. Artık şunları kullanabilirsiniz:

@Inject // or @Autowired
private ApplicationContext ctx;

4
Çok teşekkür ederim, istediğim bu! Belki baharın nasıl çalıştığını anlamak için bazı bahar kodunu okumam gerekiyor.
Jimmy

2
Çoğu durumda @Autowired kullanmak daha iyidir, ancak bunun işe yaramayabileceği başka durumlar da vardır, örneğin singleton olan bir "@Component" e sahipseniz, ancak bir oturum kapsamına sahip bir fasulye enjekte etmeniz gerektiğinde. Bağımlılıklar, uygulama bağlamı oluşturmada otomatik olarak bağlandığından, gerçekten bir oturum parçacığı enjekte edilmeyecektir, uygulama bağlamına bir referans alarak, oturum çekirdeğini programlı olarak geri getirebilir ve böylece oturum fasulye örneğini doğru bir şekilde döndürebilirsiniz.
raspacorp

Bunun yerine Spring'in dinamik olarak oluşturulmuş bir proxy sınıfını enjekte etmesini beklerdim - böyle bir sınıfın uygulama kapsamı vardır, ancak erişildiğinde bir oturum kapsamı örneğine delege eder veya şu anda çalışan iş parçacığına bağlı bir istek olmadığı için bir istisna atar
xorcus

@raspacorp eğer seans kapsam fasulyesi enjekte ApplicationContextedilemiyorsa ApplicationContextAware instanceikisinden de alınamaz . Çünkü enjekte edilenle ApplicationContextAware instanceaynı applicationContextnesneden bir fasulye alır .
Tiina

10

Bahar kaynak kodu nasıl ApplicationContextAware çalışmalarını anlatmak üzere
kullandığınızda ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ise AbstractApplicationContextsınıf, refresh()metot aşağıdaki kodu vardır:

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

bu yöntemi girin, beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));ApplicationContextAwareProcessor'ı AbstractrBeanFactory'ye ekleyecektir.

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));
...........

Spring AbstractAutowireCapableBeanFactory, bean in yönteminde başlatıldığında , fasulye post sürecini uygulamaya initializeBeançağırın applyBeanPostProcessorsBeforeInitialization. süreç, applicationContext'i enjekte etmeyi içerir.

@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, postProcessBeforeInitialization yöntemini yürütmek için Object uyguladığında, örneğin ApplicationContextAwareProcessordaha önce eklenenler.

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

İçinde çalıştığı ApplicationContext'ten haberdar edilmek isteyen herhangi bir nesne tarafından uygulanacak arabirim.

yukarıdaki Bahar dokümanı web sitesi https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContextAware.html'den alınmıştır .

Yani, o anda bir şeyler yapmak istiyorsanız, Spring konteyneri başladığında çağrılmış gibi görünüyordu.

Bağlamı ayarlamak için sadece bir yöntemi var, bu yüzden bağlamı anlayacak ve şimdi zaten bağlamda bir şeyler yapacaksınız.


-1

Spring konteyner hizmetlerini çağırabileceğiniz geçerli uygulama bağlamı olan ApplicationContextAware Arayüzü. Sınıfta aşağıdaki yöntemle enjekte edilen current applicationContext örneğini alabiliriz

public void setApplicationContext(ApplicationContext context) throws BeansException.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.