Spring之ApplicationContextAware接口详解

在Spring中,当一个bean实现了ApplicationContextAware接口,这个bean便可以获取到ApplicationContext对象,进而获取应用上下文中的bean。

代码实例

package com.huawei.nlz.springplayground.applicationcontextaware;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringBeanFactory implements ApplicationContextAware {
    private static ApplicationContext context;

    /**
     * 从Spring应用上下文中获取特定类型的bean
     *
     * @param c   类型的Class对象
     * @param <T> 类型
     * @return bean
     */
    public static <T> T getBean(Class<T> c) {
        return context.getBean(c);
    }

    /**
     * 从Spring应用上下文中获取指定名字的特定类型的bean
     *
     * @param name bean名字
     * @param c    类型的Class对象
     * @param <T>  类型
     * @return bean
     */
    public static <T> T getBean(String name, Class<T> c) {
        return context.getBean(name, c);
    }

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

这里的SpringBeanFactory被声明为要为之创建单例bean,然后在setApplicationContext回调中,把Spring传过来的ApplicationContext保存到自己内部的静态字段context上,然后将从context上获取bean封装为公共的静态方法开放给其他类调用。

应用场景

一般的应用场景即是上面所示的bean的工厂。以上面的类为例,我们可以通过SpringBeanFactory.getBean("myBean", MyBean.class)来获取bean。这使得在一些无法注入的地方我们也可以获取到bean,比如Util类中,为我们带来极大的便利。

源码分析

最后我们跟踪一下Spring的源码,看看具体是怎么执行的。

我们进入AbstractApplicationContext的refresh方法,

@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
    // Prepare this context for refreshing.
	prepareRefresh();

	// Tell the subclass to refresh the internal bean factory.
	ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

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

	try {
		// Allows post-processing of the bean factory in context subclasses.
		postProcessBeanFactory(beanFactory);

		// Invoke factory processors registered as beans in the context.
		invokeBeanFactoryPostProcessors(beanFactory);
...

进入prepareBeanFactory,

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));
	beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
	beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
	beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
	beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
...

可以看到Spring自动给添加上了一个BeanPostProcessor--ApplicationContextAwareProcessor,

我们看看ApplicationContextAwareProcessor,

class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;


	/**
	 * Create a new ApplicationContextAwareProcessor for the given context.
	 */
	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	}


	@Override
	@Nullable
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

		if (System.getSecurityManager() != null &&
				(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
						bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
						bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	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(this.embeddedValueResolver);
			}
			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);
			}
		}
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		return bean;
	}

}

ApplicationContextAwareProcessor确实实现了BeanPostProcessor接口,它会判断bean的类型,如果bean是ApplicationContextAware接口,那么就调用这个对象的setApplicationContext方法。

那么BeanPostProcessor是何时调用的呢?

其代码流程如下: AbstractApplicationContext.refresh -> AbstractApplicationContext.finishBeanFactoryInitialization -> ConfigurableListableBeanFactory(DefaultListableBeanFactory).preInstantiateSingletons -> DefaultListableBeanFactory.getBean -> DefaultListableBeanFactory.doGetBean -> DefaultListableBeanFactory.createBean -> AbstractAutowireCapableBeanFactory.doCreateBean -> AbstractAutowireCapableBeanFactory.initializeBean。

我们看下最末尾的AbstractAutowireCapableBeanFactory的initializeBean方法:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

其中applyBeanPostProcessorsBeforeInitialization会对该bean对象应用所有的beanPostProcessors:

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

...

public List<BeanPostProcessor> getBeanPostProcessors() {
	return this.beanPostProcessors;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值