以jetty服务器为例:
引用:ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。
附:初始化bean最终执行的好像都是org.springframework.beans.BeanUtils.java类的方法。
一、容器启动加载内容:
可是,启动容器时,ContextLoaderListener实现类的监听器在哪里被调用的呢,比如jetty,其实是被org.mortbay.jetty.handler.ContextHandler类调用的,再往上看,就是org.mortbay.jetty.webapp.WebAppContext的doStart方法。由ContextHandler成员变量_contextListeners.contextInitialized(event);在项目启动时来调用,而此时的event参数,是servlet-api-x.x.jar中的ServletContext接口,实现类由不同web容器各自实现,比如jetty为ContextHandler中的SContext。
所以,容器启动时会调用所有此监听器实现类,那么就可以通过实现类做点什么...
配置文件如下(其中名字contextConfigLocation不能变,它是ContextLoader类中的常量):
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext-*.xml,/WEB-INF/applicationContext.xml,/WEB-INF/classes/applicationContext-*.xml lt;/param-value> </context-param>
加载好的容器对象为WebApplicationContext,并将其放入ServletContext中(供所有servlet使用)。而WebApplicationContext的默认实现类为XmlWebApplicationContext,查看源码可得,在/org/springframework/web/context/ContextLoader.properties配置默认的容器类。XmlWebApplicationContext初始化如下:
1、被ContextLoader调用configureAndRefreshWebApplicationContext(cwac, servletContext);初始化Bean工厂类以及其他配置。
2、默认读取配置文件:DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml",我们一般自己定义,有多个时用;分开,这个配置在上面有提到。
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
// The application context id is still set to its original default value
// -> assign a more useful id based on available information
String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
if (idParam != null) {
wac.setId(idParam);
}
else {
// Generate default id...值为(例):org.springframework.web.context.WebApplicationContext:/findhome-web
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(sc.getContextPath()));
}
}
wac.setServletContext(sc);
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
wac.setConfigLocation(configLocationParam);//值为(例):classpath:spring.xml
}
// The wac environment's #initPropertySources will be called in any case when the context
// is refreshed; do it eagerly here to ensure servlet property sources are in place for
// use in any post-processing or initialization that occurs below prior to #refresh
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
}
customizeContext(sc, wac);
wac.refresh();//初始化
}
其中wac.refresh();初始化的内容如下:初始化加载bean,其中通过判断是否开启Scanner扫描注解方式,并生成对应的bean。扫描到的bean放在beanFactory,用于后面的加载。
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) {
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进行实例化,其实无论是数据库配置,还是redis、消息队列等第三方功能组件,都是配置一个bean类放到spring工厂中提供调用,其需要的参数不同,在配置中配置对应需要的参数即可。点进去可看的如下代码:
@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()初始化,而getBean()调用底层方法,可以看看它的实现,在源码中可以看的,类A加载时如果依赖B,那就先去加载B,再回来加载A。其中,生成对象的createBean(beanName, mbd, args);方法中,有一句代码很重要,如下:
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
看看它的实现,
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// 实际创建的Bean的包装容器
BeanWrapper instanceWrapper = null;
//对于单例模式下的Bean,可能在创建过程中断过,暂时放在缓存里
if (mbd.isSingleton()) {
//从缓存中恢复未创建完成的Bean对象
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//真正创建对象的入口
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
// Allow post-processors to modify the merged bean definition.
//Bean创建后处理
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 解决循环引用的地方,当singleton遇到循环引用时,会放入singletonsCurrentlyInCreation中,暂停
// 在此处从singletonsCurrentlyInCreation中再拿到这个未完成初始化的对象
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// 下面依赖注入
Object exposedObject = bean;
try {
//依赖注入的方法入口
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// 处理未完成注入的循环引用的bean
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
继续往下看,
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
//获得需要创建的Bean的Class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 确定需要创建的Bean的实例的类可以实例化
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
//如果存在工厂方法,则使用工厂方法去实例化类
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 使用自动状态的构造方式进行实例化
// 下面10行的代码是在减少重复创建bean的工作量。如果已经创建过同样的bean,直接使用上一次的配置属性
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//自动装配构造实例
if (resolved) {
if (autowireNecessary) {
//返回自动装配的实例化结果
return autowireConstructor(beanName, mbd, null, null);
}
else {
//使用构造方法进行构造
return instantiateBean(beanName, mbd);
}
}
// 确定需要使用的构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//自动装配构造方法
return autowireConstructor(beanName, mbd, ctors, args);
}
// 使用默认的无参数的构造方法
return instantiateBean(beanName, mbd);
}
其中,instantiateBean方法如下:
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;//构建出来的Bean实例
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
// 提升权限
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
//调用具体实例化方法
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
//调用具体实例化方法
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
//包装创建好的实例
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
继续,这里有两种初始化方式,使用JDK的反射方法、CGLIB的方法:
共同点主要用于:
单例类调用原型类,默认情况被调用的原形类仍是单例模式(即单例模式覆盖了原型模式),而通过lookup-method属性给单例类注入原型模式类的不同的实例。
他们之间有 什么区别呢?
其实很多时候 使用Autowired 即可,但是,使用场景还是有所不同的。Autowired用于给一个单例对象注入另一个单例对象。但是如果想注入另外一个原型对象。那么久行不通了!这个时候就使用lookup-method 吧!
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// 这个if-else 把bean的初始化分为两类
//如果定义了look-up method(针对虚拟类获取原型bean的虚拟方法) 或replace method(用继承MethodReplacer接口的类来做) 将使用CGLIB初始化
//否则使用JDK的反射
if (bd.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;//获得构造方法
synchronized (bd.constructorArgumentLock) {
//使用工厂方法 或者 构造器
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
@Override
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Exception ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// 使用CGLIB初始化
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
而两种初始化方式代码分别为:
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
//获得访问权限
ReflectionUtils.makeAccessible(ctor);
//利用反射生成实例
return ctor.newInstance(args);
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor.getDeclaringClass(),
"Constructor threw exception", ex.getTargetException());
}
}
public Object instantiate(Constructor<?> ctor, Object... args) {
//利用CGLIB生成Class对象
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
//利用反射对CGLIB生成的Class对象实例化
instance = BeanUtils.instantiate(subclass);
}
else {
try {
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
//利用CGLIB进行实例化
instance = enhancedSubclassConstructor.newInstance(args);
}
catch (Exception ex) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
}
}
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
//在此处设置lookup和replacemethod
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}
private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
enhancer.setCallbackTypes(CALLBACK_TYPES);
return enhancer.createClass();
}
二、XmlWebApplicationContext的实现:
首先,XmlWebApplicationContext->AbstractRefreshableWebApplicationContext->AbstractRefreshableConfigApplicationContext和ConfigurableWebApplicationContext,
其中,ConfigurableWebApplicationContext->WebApplicationContext->ApplicationContext