本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试。
记录日期:2022.1.4
大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习。
文章目录
框架原理 - Spring(五)之Spring IOC 源码prepareBeanFactory()
AbstractApplicationContext#prepareBeanFactory(beanFactory)
前面的内容已经初始化Bean容器实例,下面要开始准备bean容器了。
// AbstractApplicationContext 680
/** * 配置工厂的标准上下文特征,例如上下文的类加载器和后处理器。 * @param beanFactory the BeanFactory to configure */
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置beanFactory的classLoader为当前context的classLoader
beanFactory.setBeanClassLoader(getClassLoader());
// 是否需要忽略el表达式
if (!shouldIgnoreSpel) {
// 设置beanFactory的表达式语言处理器,spring 3增加了表达式语言的支持
// 默认可以使用#{bean.xxx}的形式来调用相关的属性
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
// 为beanFactory增加一个默认的propertyEditor,这个主要是对bean的属性等设置管理一个工具
// 详情见:https://blog.csdn.net/cuichunchi/article/details/90407632
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 添加一个 BeanPostProcessor,这个 processor 比较简单
// 实现了 Aware 接口的几个特殊的 beans 在初始化的时候,这个 processor 负责回调
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 下面几行的意思就是,如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们,
// Spring 会通过其他方式来处理这些依赖。
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.ignoreDependencyInterface(ApplicationStartupAware.class);
/** - 设置了几个自动装配的特殊规则 - * 下面几行就是为特殊的几个 bean 赋值,如果有 bean 依赖了以下几个,会注入这边相应的值, * 之前我们说过,"当前 ApplicationContext 持有一个 BeanFactory",这里解释了第一行 * ApplicationContext 继承了 ResourceLoader、ApplicationEventPublisher、MessageSource * 所以对于这几个,可以赋值为 this,注意 this 是一个 ApplicationContext * 那这里怎么没看到为 MessageSource 赋值呢?那是因为 MessageSource 被注册成为了一个普通的 bean */
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 这个 BeanPostProcessor 也很简单,在 bean 实例化后,如果是 ApplicationListener 的子类,
// 那么将其添加到 listener 列表中,可以理解成:注册事件***
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 这里涉及到特殊的 bean,名为:loadTimeWeaver,这不是我们的重点,忽略它
// 作用是增加对AspectJ的支持
if (!NativeDetector.inNativeImage() && 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()));
}
/** * 从下面几行代码我们可以知道,Spring 往往很 "智能" 就是因为它会帮我们默认注册一些有用的 bean, * 我们也可以选择覆盖 - 添加默认的系统环境bean - */
// 如果没有定义 "environment" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
// 如果没有定义 "systemProperties" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
// 如果没有定义 "systemEnvironment" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
// 如果没有定义 "applicationStartup" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
引入:Aware接口
Aware
接口的注释上说明:该接口是一个标记接口,如果某个bean实现了该接口,一般会有一个BeanPostProcessor类对其进行处理,具体方法的定义由实现了该接口的子接口进行定义,但是通常该子接口应该只包含一个方法,且该方法的返回值为void,参数只有一个
。
实现这些 Aware
接口的Bean在被实例化之后,可以取得一些相对应的资源。
例如实现BeanFactoryAware的Bean在实例化后,Spring容器将会注入 BeanFactory
的实例,而实现ApplicationContextAware
的Bean,在Bean被实例化后,将会被注入 ApplicationContext
的实例等等。
下面来列出主要的 Aware
接口子类:
LoadTimeWeaverAware
:加载Spring Bean时织入第三方模块,如AspectJBeanClassLoaderAware
:加载Spring Bean的类加载器BootstrapContextAware
:资源适配器BootstrapContext,如JCA,CCIResourceLoaderAware
:底层访问资源的加载器BeanFactoryAware
:声明BeanFactoryPortletConfigAware
:PortletConfigPortletContextAware
:PortletContextServletConfigAware
:ServletConfigServletContextAware
:ServletContextMessageSourceAware
:国际化ApplicationEventPublisherAware
,应用事件NotificationPublisherAware
:JMX通知org.springframework.beans.factory.BeanNameAware
:声明Spring Bean的名字
来看几个Aware接口的子类:
// EnvironmentAware
public interface EnvironmentAware extends Aware {
/** * Set the {@code Environment} that this component runs in. */
void setEnvironment(Environment environment);
}
// EmbeddedValueResolverAware
public interface EmbeddedValueResolverAware extends Aware {
/** * Set the StringValueResolver to use for resolving embedded definition values. */
void setEmbeddedValueResolver(StringValueResolver resolver);
}
// ResourceLoaderAware
public interface ResourceLoaderAware extends Aware {
/** * Set the ResourceLoader that this object runs in. * <p>This might be a ResourcePatternResolver, which can be checked * through {@code instanceof ResourcePatternResolver}. See also the * {@code ResourcePatternUtils.getResourcePatternResolver} method. * <p>Invoked after population of normal bean properties but before an init callback * like InitializingBean's {@code afterPropertiesSet} or a custom init-method. * Invoked before ApplicationContextAware's {@code setApplicationContext}. * @param resourceLoader the ResourceLoader object to be used by this object * @see org.springframework.core.io.support.ResourcePatternResolver * @see org.springframework.core.io.support.ResourcePatternUtils#getResourcePatternResolver */
void setResourceLoader(ResourceLoader resourceLoader);
}
// ApplicationEventPublisherAware
public interface ApplicationEventPublisherAware extends Aware {
/** * Set the ApplicationEventPublisher that this object runs in. * <p>Invoked after population of normal bean properties but before an init * callback like InitializingBean's afterPropertiesSet or a custom init-method. * Invoked before ApplicationContextAware's setApplicationContext. * @param applicationEventPublisher event publisher to be used by this object */
void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher);
}
// MessageSourceAware
public interface MessageSourceAware extends Aware {
/** * Set the MessageSource that this object runs in. * <p>Invoked after population of normal bean properties but before an init * callback like InitializingBean's afterPropertiesSet or a custom init-method. * Invoked before ApplicationContextAware's setApplicationContext. * @param messageSource message source to be used by this object */
void setMessageSource(MessageSource messageSource);
}
// ApplicationContextAware
public interface ApplicationContextAware extends Aware {
/** * Set the ApplicationContext that this object runs in. * Normally this call will be used to initialize the object. * <p>Invoked after population of normal bean properties but before an init callback such * as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()} * or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader}, * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and * {@link MessageSourceAware}, if applicable. * @param applicationContext the ApplicationContext object to be used by this object * @throws ApplicationContextException in case of context initialization errors * @throws BeansException if thrown by application context methods * @see org.springframework.beans.factory.BeanInitializationException */
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
可以看到各个Aware都满足于只包含一个方法,且该方法的返回值为void,参数只有一个
的要求。
我们可以来挑选几个Aware接口继续举例。
实现BeanNameAware
和 EmbeddedValueResolverAware
:
/*** * 实现了BeanNameAware,可以获取到当前bean在IOC容器中的名字 * 注意该Aware的调用在前置处理器applyBeanPostProcessorsBeforeInitialization方法之前 * * 实现了EmbeddedValueResolverAware,可以利用resolver来解析字符串表达式(el表达式) */
@Component
public class Tiger implements BeanNameAware, EmbeddedValueResolverAware {
private String name = "老虎";
public void setBeanName(String name) {
System.err.println("当前bean的名字为:" + name);
}
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String val = resolver.resolveStringValue("当前系统为${os.name},表达式3*8的结果为:#{3*8}");
System.err.println("解析后的字符串为===" + val);
}
}
// 控制台输出
// 当前bean的名字为: tiger
//当前系统为Windows 10,表达式3*8的结果为:24
其他就先不介绍了。