以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(); }另外,lookup-method & replace-method 用于哪些地方呢?
共同点主要用于:
单例类调用原型类,默认情况被调用的原形类仍是单例模式(即单例模式覆盖了原型模式),而通过lookup-method属性给单例类注入原型模式类的不同的实例。
他们之间有 什么区别呢?
其实很多时候 使用Autowired 即可,但是,使用场景还是有所不同的。Autowired用于给一个单例对象注入另一个单例对象。但是如果想注入另外一个原型对象。那么久行不通了!这个时候就使用lookup-method 吧!
二、XmlWebApplicationContext的实现:
首先,XmlWebApplicationContext->AbstractRefreshableWebApplicationContext->AbstractRefreshableConfigApplicationContext和ConfigurableWebApplicationContext,
其中,ConfigurableWebApplicationContext->WebApplicationContext->ApplicationContext