目錄
StandardBeanExpressionResolver
4)、ApplicationContextAwareProcessor
6)、registerResolvableDependency
7)、ApplicationListenerDetector
BeanFactoryUtils.transformedBeanName
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);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
1)、設置BeanFactory類加載器
beanFactory.setBeanClassLoader(getClassLoader());
如果爲null,則從當前線程獲取:
Thread.currentThread().getContextClassLoader();
2)、設置Spring Expression解析器
設置後BeanFactory則擁有了解析Spring Expression的能力,這個我們在項目中某個類,實現BeanFactoryAware其實是完全可以使用的,之前沒有注意。下面分析
beanFactory.setBeanExpressionResolver(new
StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
StandardBeanExpressionResolver
public class StandardBeanExpressionResolver implements BeanExpressionResolver {
/** Default expression prefix: "#{". */
public static final String DEFAULT_EXPRESSION_PREFIX = "#{";
/** Default expression suffix: "}". */
public static final String DEFAULT_EXPRESSION_SUFFIX = "}";
private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX;
private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX;
private ExpressionParser expressionParser;
private final Map<String, Expression> expressionCache = new ConcurrentHashMap<>(256);
private final Map<BeanExpressionContext, StandardEvaluationContext> evaluationCache = new ConcurrentHashMap<>(8);
private final ParserContext beanExpressionParserContext = new ParserContext() {
@Override
public boolean isTemplate() {
return true;
}
@Override
public String getExpressionPrefix() {
return expressionPrefix;
}
@Override
public String getExpressionSuffix() {
return expressionSuffix;
}
};
public StandardBeanExpressionResolver() {
this.expressionParser = new SpelExpressionParser();
}
public StandardBeanExpressionResolver(@Nullable ClassLoader beanClassLoader) {
this.expressionParser = new SpelExpressionParser(new SpelParserConfiguration(null, beanClassLoader));
}
/**
* Set the prefix that an expression string starts with.
* The default is "#{".
* @see #DEFAULT_EXPRESSION_PREFIX
*/
public void setExpressionPrefix(String expressionPrefix) {
this.expressionPrefix = expressionPrefix;
}
@Override
@Nullable
public Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException {
if (!StringUtils.hasLength(value)) {
return value;
}
try {
Expression expr = this.expressionCache.get(value);
if (expr == null) {
expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext);
this.expressionCache.put(value, expr);
}
StandardEvaluationContext sec = this.evaluationCache.get(evalContext);
if (sec == null) {
sec = new StandardEvaluationContext(evalContext);
sec.addPropertyAccessor(new BeanExpressionContextAccessor());
sec.addPropertyAccessor(new BeanFactoryAccessor());
sec.addPropertyAccessor(new MapAccessor());
sec.addPropertyAccessor(new EnvironmentAccessor());
sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
if (conversionService != null) {
sec.setTypeConverter(new StandardTypeConverter(conversionService));
}
customizeEvaluationContext(sec);
this.evaluationCache.put(evalContext, sec);
}
return expr.getValue(sec);
}
catch (Throwable ex) {
throw new BeanExpressionException("Expression parsing failed", ex);
}
}
}
其實現了BeanExpressionResolver接口,就一個接口方法,解析當前的字符串:
Object evaluate(@Nullable String value, BeanExpressionContext evalContext)
throws BeansException;
Spring Expression比如@Value註解,比如@Value("#{'kevin.demo'}")則需要改解析器進行解析,所以會有DEFAULT_EXPRESSION_PREFIX和DEFAULT_EXPRESSION_SUFFIX進行處理。在有參獲取無參構造都會默認初始化SpelExpressionParser和ParserContext進行解析的時候需要。並且實現了evaluate方法,則擁有解析的能力了,更多的東西后面專門分析吧。
3)、ResourceEditorRegistrar
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this,
getEnvironment()));
public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
private final PropertyResolver propertyResolver;
private final ResourceLoader resourceLoader;
public ResourceEditorRegistrar(ResourceLoader resourceLoader, PropertyResolver propertyResolver) {
this.resourceLoader = resourceLoader;
this.propertyResolver = propertyResolver;
}
// 後續調用該方法後就擁有了解析File、PathURL等能力了
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
doRegisterEditor(registry, Resource.class, baseEditor);
doRegisterEditor(registry, ContextResource.class, baseEditor);
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
doRegisterEditor(registry, Path.class, new PathEditor(baseEditor));
doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
ClassLoader classLoader = this.resourceLoader.getClassLoader();
doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));
if (this.resourceLoader instanceof ResourcePatternResolver) {
doRegisterEditor(registry, Resource[].class,
new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver));
}
}
private void doRegisterEditor(PropertyEditorRegistry registry, Class<?> requiredType, PropertyEditor editor) {
if (registry instanceof PropertyEditorRegistrySupport) {
((PropertyEditorRegistrySupport) registry).overrideDefaultEditor(requiredType, editor);
}
else {
registry.registerCustomEditor(requiredType, editor);
}
}
}
構造函數初始化了解析器和類加載器,但是後續調用了registerCustomEditors方法,初始化ResourceEditor添加了很多的類型,則就擁有了解析File、URL、Path等的能力了。這個我們在項目中某個類,實現BeanFactoryAware其實是完全可以使用的,之前沒有注意。
4)、ApplicationContextAwareProcessor
非常重要的BeanPostProcessor子類,初始化並且將當前的Processor註冊到BeanFactory的beanPostProcessors中,後續爲每個實現了EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware或者ApplicationContextAware的子類回調該方法,設置屬性,或者回調方法。調用postProcessBeforeInitialization方法,後續分析。
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new
EmbeddedValueResolver(applicationContext.getBeanFactory());
}
}
5)、ignoreDependencyInterface
在依賴注入bean的時候,如果當前Bean實現了某些接口是我們特點的,不用依賴注入的則需要進行忽略。在這裏進行添加一部分。添加到AbstractAutowireCapableBeanFactory的ignoredDependencyInterfaces中。其實也就是上面ApplicationContextAwareProcessor需要回調的類型。
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
6)、registerResolvableDependency
設置自動裝配(按照類型)的一些特殊規則,當發現需要註冊的當前bean實現了某接口,則直接將該Map的value值注入進去。後續getBean時候詳細分析。添加到DefaultListableBeanFactory的resolvableDependencies中。
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
7)、ApplicationListenerDetector
又是一個特殊的BeanPostProcessor,同時實現了MergedBeanDefinitionPostProcessor(MergedBeanDefinition的回調,即合併了父類的屬性等的beanDefinition)和DestructionAwareBeanPostProcessor(註銷實現了的ApplicatonEvent)。
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,
Class<?> beanType, String beanName);
default void resetBeanDefinition(String beanName) {
}
}
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
default boolean requiresDestruction(Object bean) {
return true;
}
}
class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor,
MergedBeanDefinitionPostProcessor {
private final transient AbstractApplicationContext applicationContext;
private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256);
public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,
Class<?> beanType, String beanName) {
this.singletonNames.put(beanName, beanDefinition.isSingleton());
}
}
ApplicationListenerDetector實現了上面所有機接口的方法,並且能看出在BeanDefinition進行Merge後會調用postProcessMergedBeanDefinition方法將值注入到singletonNames中使用,後續分析。
8)、LOAD_TIME_WEAVER_BEAN_NAME
1)、containsBean
使用BeanFactory的containsBean方法判斷是否擁有Bean,很多地方都使用到了,所以這裏看一下是怎麼進行判斷的。最終會調用到AbstractBeanFactory的方法,先獲取真實的beanName(傳入的可能是別名);從單利bean或者BeanDefinition容器中獲取;最後從父工廠中獲取。非常清晰的思路。
public boolean containsBean(String name) {
String beanName = transformedBeanName(name);
if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
}
// Not found -> check parent.
BeanFactory parentBeanFactory = getParentBeanFactory();
return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
}
其實很多地方也調用了transformedBeanName方法,因爲我們傳入的可能是別名,不是beanName。所以需要查找真正的BeanName,這裏也分析一下。
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
BeanFactoryUtils.transformedBeanName
當前傳入的可能是FactoryBean類型的bean,並且是獲取FactoryBean的,所以在BeanFactoryUtils中處理(就是截取字符串):
public static String transformedBeanName(String name) {
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
containsSingleton
從DefaultSingletonBeanRegistry的singletonObjects中判斷
public boolean containsSingleton(String beanName) {
return this.singletonObjects.containsKey(beanName);
}
containsBeanDefinition
從DefaultListableBeanFactory的beanDefinitionMap中判斷
public boolean containsBeanDefinition(String beanName) {
return this.beanDefinitionMap.containsKey(beanName);
}
2)、添加織入相關處理
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(
beanFactory.getBeanClassLoader()));
}
如果需要進行織入則添加LoadTimeWeaverAwareProcessor,ContextTypeMatchClassLoader。
9)、Environment相關注成Bean
上一篇分析過StandardEnvironment的初始化過程,從System中獲取了很多配置讓Spring容器進行管理,現在爲了方便,直接在ApplicationContext(或者說BeanFactory)中進行注入。所以相關環境變量直接在容器中是可以拿到的,當然Spring Boot的Actuator也是建立在該基礎上的,詳細見上一篇
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME,
getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME,
getEnvironment().getSystemEnvironment());
}