spring源码分析:Aware接口让你的bean对容器直接操作
Posted Small leaf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring源码分析:Aware接口让你的bean对容器直接操作相关的知识,希望对你有一定的参考价值。
相信大家都知道很多其他框架,比如mybatis,shiro等等,spring框架本身有些类会实现ApplicationContextAware,BeanFactoryAware或者等等其他XXXAware,这是用来干嘛呢?
spring容器来管理bean。如果说bean需要知道容器的状态获取容器的信息直接使用容器那么就需要实现XXXAware来实现了。
以下具体讲解spring是如何让bean直接操作spring容器的。
package com.share1024.aware;
import org.springframework.stereotype.Component;
/**
* @author : yesheng
* @Description :
* @Date : 2017/11/7
*/
@Component
public class User
public void say()
System.out.println("i am a student");
package com.share1024.aware;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import javax.servlet.ServletConfig;
/**
* @author : yesheng
* @Description :
* @Date : 2017/11/7
*/
@Component
public class CustomApplicationAware implements ApplicationContextAware ,BeanFactoryAware
private ApplicationContext applicationContext;
private BeanFactory beanFactory;
private ServletConfig servletConfig;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
this.applicationContext = applicationContext;
public void say()
User user = (User) applicationContext.getBean("user");
user.say();
public void setBeanFactory(BeanFactory beanFactory) throws BeansException
this.beanFactory = beanFactory;
public void say2()
User user = (User) beanFactory.getBean("user");
System.out.println("from beanFactory");
user.say();
package com.share1024.aware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @author : yesheng
* @Description :
* @Date : 2017/11/7
*/
@Configuration
@ComponentScan("com.share1024.aware")
public class JavaConfig
public static void main(String[] args)
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
CustomApplicationAware customApplicationAware = (CustomApplicationAware) applicationContext.getBean("customApplicationAware");
customApplicationAware.say();
customApplicationAware.say2();
运行结果
i am a student
from beanFactory
i am a student
CustomApplicationAware实现了ApplicationContextAware和BeanFactoryAware接口。通过set方法就让容器获得ApplicationContext和BeanFactory对象,那么我们可以用这两个对象对spring容器进行操作了。
使用起来确实很简单,我们去看看是如何实现这两个set方法的,首先提下spring容器对bean初始化分为三个步骤,第一资源文件的定位(xml,javaconfig),二、BeanDefinition的载入,三向IOC容器注册这些BeanDefinition。
而我们这里是发现在Ioc容器的依赖注入环节。也就是getBean环节。
先看看ApplicationContextAware和BeanFactoryAware
public interface ApplicationContextAware extends Aware
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
public interface BeanFactoryAware extends Aware
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
public interface Aware
两个接口都实现了Aware,通过多态实现不同的Aware。
debug到
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
这行代码,go
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses)
this();
register(annotatedClasses);
refresh();
我这里使用的java配置文件的方式refresh是spring对bean初始化初始化,依赖注入核心环节。
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);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
catch (BeansException ex)
if (logger.isWarnEnabled())
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
finally
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
我们直接定位到finishBeanFactoryInitialization(beanFactory)。只要bean不是抽象,是单例,不是懒加载就会在这里进行依赖注入。
@Override
public void preInstantiateSingletons() throws BeansException
if (this.logger.isDebugEnabled())
this.logger.debug("Pre-instantiating singletons in " + this);
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames)
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit())
if (isFactoryBean(beanName))
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean)
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>()
@Override
public Boolean run()
return ((SmartFactoryBean<?>) factory).isEagerInit();
, getAccessControlContext());
else
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
if (isEagerInit)
getBean(beanName);
else
getBean(beanName);
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames)
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton)
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null)
AccessController.doPrivileged(new PrivilegedAction<Object>()
@Override
public Object run()
smartSingleton.afterSingletonsInstantiated();
return null;
, getAccessControlContext());
else
smartSingleton.afterSingletonsInstantiated();
直接进入getBean(beanName);
AbstractBeanFactory.doGetBean
if (mbd.isSingleton())
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>()
@Override
public Object getObject() throws BeansException
try
return createBean(beanName, mbd, args);
catch (BeansException ex)
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
);
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
getSingleton第二个参数是一个接口,传入一个自己的实现。JdbcTemplate,RedisTemplate等等很多地方都有这样的实现。
进入createBean(beanName, mbd, args);
AbstractAutowireCapableBeanFactory.createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException
if (logger.isDebugEnabled())
logger.debug("Creating instance of bean '" + beanName + "'");
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null)
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
// Prepare method overrides.
try
mbdToUse.prepareMethodOverrides();
catch (BeanDefinitionValidationException ex)
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
try
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null)
return bean;
catch (Throwable ex)
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled())
logger.debug("Finished creating instance of bean '" + beanName + "'");
return beanInstance;
进入 Object beanInstance = doCreateBean(beanName, mbdToUse, args);
大致上看这几个方法这几个
...
//初始化类的构造函数
if (instanceWrapper == null)
instanceWrapper = createBeanInstance(beanName, mbd, args);
...
Object exposedObject = bean;
try
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null)
exposedObject = initializeBean(beanName, exposedObject, mbd);
...
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd)
if (System.getSecurityManager() != null)
AccessController.doPrivileged(new PrivilegedAction<Object>()
@Override
public Object run()
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;
private void invokeAwareMethods(final String beanName, final Object bean)
if (bean instanceof Aware)
if (bean instanceof BeanNameAware)
((BeanNameAware) bean).setBeanName(beanName);
if (bean instanceof BeanClassLoaderAware)
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
if (bean instanceof BeanFactoryAware)
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
BeanNameAware、BeanClassLoaderAware、BeanFactoryAware这三个接口就在这里来具体给类来进行set。
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic())
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
@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;
ApplicationContextAwareProcessor对应的是ApplicationContextAware相应的处理类。
ApplicationContextAwareProcessor implements BeanPostProcessor
此时会调用ApplicationContextAwareProcessor.postProcessBeforeInitialization
@Override
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(new PrivilegedAction<Object>()
@Override
public Object run()
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(
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);
EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware进行处理。
从上面来看,以后我们需要bean中直接对IOC容器进行操作,可以实现相应的接口。
菜鸟不易,望有问题指出,共同进步
以上是关于spring源码分析:Aware接口让你的bean对容器直接操作的主要内容,如果未能解决你的问题,请参考以下文章
Spring原理分析-Aware接口&InitializingBean