Aware
Aware是一个接口,通常继承了该接口的都可以获得Spring提供的相关信息。
这里简单介绍常用的子接口。
ApplicationContextAware
使用ApplicationContextAware可以获得容器上下文
使用
实现ApplicationContextAware接口
@Service
public class UserService implements ApplicationContextAware {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
这样就获得了容器上下文。
EmbeddedValueResolverAware
EmbeddedValueResolverAware用于获得字符串解析器
使用
@Component
public class User implements EmbeddedValueResolverAware {
private StringValueResolver resolver;
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.resolver = resolver;
}
}
这样就获取到了字符串解析器。
字符串解析器有什么用?
@Component
public class User implements EmbeddedValueResolverAware {
private StringValueResolver resolver;
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.resolver = resolver;
}
public String getOsName() {
return resolver.resolveStringValue("${os.name}");
}
}
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
User user = annotationConfigApplicationContext.getBean(User.class);
System.out.println(user.getOsName());
}
}
输出内容
作用就是解析${},去Environment中获取数据。Environment不知道是什么的朋友可以看看我前面的文章有介绍到。
BeanNameAware
BeanNameAware可以获得BeanName
使用
实现BeanNameAware接口
@Component
public class User implements BeanNameAware {
private String beanName;
public String getBeanName() {
return beanName;
}
public void setBeanName(String name) {
beanName = name;
}
}
beanName的值就是当前bean的name。
Spring如何实现的?
以BeanNameAware为例子,从Spring初始化容器开始说起:
-
在构建AnnotationConfigApplicationContext会调用refresh()方法
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { this(); register(annotatedClasses); refresh(); }
-
在refresh()方法中调用了finishBeanFactoryInitialization实例化所有剩余的非延迟加载的单例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(); } //提高可读性省略不必要的代码 } }
-
在finishBeanFactoryInitialization中调用beanFactory.preInstantiateSingletons()
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // Register a default embedded value resolver if no bean post-processor // (such as a PropertyPlaceholderConfigurer bean) registered any before: // at this point, primarily for resolution in annotation attribute values. if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching. beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes. beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons. beanFactory.preInstantiateSingletons(); }
途中经过各种步骤
然后在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean方法中调用了initializeBean。在initializeBean再调用了invokeAwareMethods方法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; }
-
重点来了,在invokeAwareMethods中可以看到判断当前bean是否是BeanNameAware,如果是的话就调用setBeanName把beanName传递过去。
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) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
这里主要是介绍了下大概流程,具体详细过程,感兴趣的朋友可以具体看看Spring源码。