当前位置 : 主页 > 编程语言 > java >

Spring5 IOC容器解析——postProcessBeanFactory(beanFactory)方法分析

来源:互联网 收集:自由互联 发布时间:2023-02-04
前言 AbstractApplicationContext类refresh()方法中的第四个调用方法postProcessBeanFactory(beanFactory),允许容器的子类去注册postProcessor ,钩子方法。   postProcessBeanFactory方法的接口声明在AbstractAppl

前言

AbstractApplicationContext类refresh()方法中的第四个调用方法postProcessBeanFactory(beanFactory),允许容器的子类去注册postProcessor ,钩子方法。

 

postProcessBeanFactory方法的接口声明在AbstractApplicationContext类中:

/** * 在标准初始化后修改应用程序上下文的内部bean工厂。 * 所有bean定义都将被加载,但是没有bean会被实例化。 * 这允许在某些应用上下文实现中注册特殊的BeanPostProcessors等。 * * Modify the application context's internal bean factory after its standard * initialization. All bean definitions will have been loaded, but no beans * will have been instantiated yet. This allows for registering special * BeanPostProcessors etc in certain ApplicationContext implementations. * @param beanFactory the bean factory used by the application context 应用环境下的Bean工厂 */ protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { }

postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

此方法的实现在AbstractRefreshableWebApplicationContext类中,它是XmlWebApplicationContext的父类。进入方法查看:

/** * Register request/session scopes, a {@link ServletContextAwareProcessor}, etc. * 注册request/session scopes,一个ServletContextAwareProcessor处理器等。 */ @Override protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { //ServletContextAwareProcessor中拿到应用上下文持有的servletContext引用和servletConfig引用 //1.添加ServletContextAwareProcessor处理器 beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig)); //在自动注入时忽略指定的依赖接口 //通常被应用上下文用来注册以其他方式解析的依赖项 beanFactory.ignoreDependencyInterface(ServletContextAware.class); beanFactory.ignoreDependencyInterface(ServletConfigAware.class); //2.注册web应用的scopes WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); //3.注册和环境有关的beans WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig); }

addBeanPostProcessor

此方法的实现在AbstractBeanFactory类中

 

这里要注册的处理器ServletContextAwareProcessor带有Aware单词,这个单词是“有意识、能意识到”的意思,个人理解就是能意识到ServletContext的存在,也就是能拿到ServletContext的引用,或者能对其进行设置。

//1.添加ServletContextAwareProcessor处理器 beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig)); /** * 添加一个新的BeanPostProcessor,在工厂创建bean的时候会应用得到。 * 在工厂配置时被调用。 * 注意:Post-processors是按照注册的顺序被提交的 * 任何通过实现Ordered接口的排序表达式都将被忽略。 * 注意,自动检测的post-processors(作为一个在ApplicationContext的bean)总是在编程方式注册后才会被使用 * @param beanPostProcessor the post-processor to register */ @Override public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null"); // Remove from old position, if any //beanPostProcessors是一个ArrayList,持有在创建bean时被应用的BeanPostProcessors this.beanPostProcessors.remove(beanPostProcessor); // Track whether it is instantiation/destruction aware //InstantiationAwareBeanPostProcessor这个接口有两个方法 //一个在实例化之前被调用 //一个在实例化之后,初始化之前被调用,可以用来做一些特殊用途,比如代理 if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { this.hasInstantiationAwareBeanPostProcessors = true; } //DestructionAwareBeanPostProcessor这个接口只有一个方法,在被销毁前调用 if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) { this.hasDestructionAwareBeanPostProcessors = true; } // Add to end of list this.beanPostProcessors.add(beanPostProcessor); }

registerWebApplicationScopes

此方法的实现在WebApplicationContextUtils类中

//2.注册web应用的scopes WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); /** * Register web-specific scopes ("request", "session", "globalSession", "application") * with the given BeanFactory, as used by the WebApplicationContext. * 注册web特有的scopes("request", "session", "globalSession", "application")到指定的bean工厂 * 被WebApplicationContext使用 * @param beanFactory the BeanFactory to configure * @param sc the ServletContext that we're running within */ public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory, @Nullable ServletContext sc) { //2.1注册request Scope beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope()); //注册session Scope beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope()); if (sc != null) { ServletContextScope appScope = new ServletContextScope(sc); //注册application Scope beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope); // Register as ServletContext attribute, for ContextCleanupListener to detect it. // 为了能让ContextCleanupListener监听器检测到, // 将application Scope作为ServletContext的属性进行注册 sc.setAttribute(ServletContextScope.class.getName(), appScope); } //ServletRequest.class为key,对象为value放入到了beanFactory的resolvableDependencies属性中 //resolvableDependencies是一个ConcurrentHashMap,映射依赖类型和对应的被注入的value //value要是依赖类型的实例,要不value就应该是个ObjectFactory //ObjectFactory和FactoryBean的区别可以看下文参考 beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory()); beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory()); beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory()); beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory()); //是否存在jsf if (jsfPresent) { FacesDependencyRegistrar.registerFacesDependencies(beanFactory); } }

registerScope

此方法的实现在AbstractBeanFactory类中

//2.1注册request Scope beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope()); @Override public void registerScope(String scopeName, Scope scope) { Assert.notNull(scopeName, "Scope identifier must not be null"); Assert.notNull(scope, "Scope must not be null"); //singleton和prototype在这个方法中不进行注册 if (SCOPE_SINGLETON.equals(scopeName) || SCOPE_PROTOTYPE.equals(scopeName)) { //不能替换已存在的 singleton scope和 prototype scope throw new IllegalArgumentException("Cannot replace existing scopes 'singleton' and 'prototype'"); } //scopes是AbstractBeanFactory的LinkedHashMap属性 Scope previous = this.scopes.put(scopeName, scope); //打印日志 if (previous != null && previous != scope) { //对已经注册过的scope进行替换 if (logger.isDebugEnabled()) { logger.debug("Replacing scope '" + scopeName + "' from [" + previous + "] to [" + scope + "]"); } } else { //没注册过的和同一个实例注册两次的scope都打印日志记录下 if (logger.isTraceEnabled()) { logger.trace("Registering scope '" + scopeName + "' with implementation [" + scope + "]"); } } }

registerEnvironmentBeans

此方法的实现在WebApplicationContextUtils类中

//3.注册和环境有关的beans WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig); /** * Register web-specific environment beans ("contextParameters", "contextAttributes") * with the given BeanFactory, as used by the WebApplicationContext. * 注册web特有的environment beans ("contextParameters", "contextAttributes")到指定工厂中 * 被WebApplicationContext所使用 * @param bf the BeanFactory to configure * @param servletContext the ServletContext that we're running within * @param servletConfig the ServletConfig */ public static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf, @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) { //单例或者beanDefinition中不包含servletContext进入条件 if (servletContext != null && !bf.containsBean(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME)) { //3.1注册servletContext单例,注册方法跟踪过一次,这里再跟踪一次加深印象 bf.registerSingleton(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME, servletContext); } //单例或者beanDefinition中不包含servletConfig进入条件 if (servletConfig != null && !bf.containsBean(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME)) { //注册servletConfig单例 bf.registerSingleton(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME, servletConfig); } //单例或者beanDefinition中不包含contextParameters进入条件 if (!bf.containsBean(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME)) { Map<String, String> parameterMap = new HashMap<>(); if (servletContext != null) { Enumeration<?> paramNameEnum = servletContext.getInitParameterNames(); while (paramNameEnum.hasMoreElements()) { String paramName = (String) paramNameEnum.nextElement(); //将servletContext参数配置放入集合中 //也就是web.xml中context-param标签里的param-name和param-value parameterMap.put(paramName, servletContext.getInitParameter(paramName)); } } if (servletConfig != null) { Enumeration<?> paramNameEnum = servletConfig.getInitParameterNames(); while (paramNameEnum.hasMoreElements()) { String paramName = (String) paramNameEnum.nextElement(); //将servletConfig中的参数配置放入集合 parameterMap.put(paramName, servletConfig.getInitParameter(paramName)); } } //以contextParameters作为name,集合转换成不可修改状态,作为value,进行注册 bf.registerSingleton(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME, Collections.unmodifiableMap(parameterMap)); } //单例或者beanDefinition中不包含contextAttributes进入条件 if (!bf.containsBean(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME)) { Map<String, Object> attributeMap = new HashMap<>(); if (servletContext != null) { Enumeration<?> attrNameEnum = servletContext.getAttributeNames(); while (attrNameEnum.hasMoreElements()) { String attrName = (String) attrNameEnum.nextElement(); //将servletContext中设置的Attribute放入集合 attributeMap.put(attrName, servletContext.getAttribute(attrName)); } } //以contextAttributes作为name,集合转换成不可修改状态,作为value,进行注册 bf.registerSingleton(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME, Collections.unmodifiableMap(attributeMap)); } }

registerSingleton

此方法的实现在DefaultListableBeanFactory类中

//3.1注册servletContext单例,注册方法跟踪过一次,这里再跟踪一次加深印象 bf.registerSingleton(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME, servletContext); public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { @Override public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { //3.1.1调用父类方法,注册单例 super.registerSingleton(beanName, singletonObject); // 仍然处于启动注册阶段 //属于手动注册情况 updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName)); //删除按照类型映射有关的任何假设 clearByTypeCache(); } private void updateManualSingletonNames(Consumer<Set<String>> action, Predicate<Set<String>> condition) { //AbstractBeanFactory类中有个集合属性alreadyCreated //里面保存在至少被创建过一次的beanName //如果这个集合中存在beanName,那么说明已经进入了bean创建阶段 if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) // 无法再修改启动时集合元素(为了稳定迭代) synchronized (this.beanDefinitionMap) { //beanName不在beanDefinitionMap中,说明是手动注册 if (condition.test(this.manualSingletonNames)) { Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames); action.accept(updatedSingletons); this.manualSingletonNames = updatedSingletons; } } } else { // Still in startup registration phase if (condition.test(this.manualSingletonNames)) { action.accept(this.manualSingletonNames); } } } /** * Remove any assumptions about by-type mappings. * 删除按照类型映射有关的任何假设 */ private void clearByTypeCache() { //allBeanNamesByType是单例和非单例beanName的映射,key是依赖类型 this.allBeanNamesByType.clear(); //仅单例beanName的映射,key是依赖类型 this.singletonBeanNamesByType.clear(); } }

registerSingleton

此方法的实现在DefaultSingletonBeanRegistry类中

//3.1.1调用父类方法,注册单例 super.registerSingleton(beanName, singletonObject); public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { /** Cache of singleton objects: bean name to bean instance. */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /** Cache of singleton factories: bean name to ObjectFactory. */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); /** Cache of early singleton objects: bean name to bean instance. */ private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); /** Set of registered singletons, containing the bean names in registration order. */ private final Set<String> registeredSingletons = new LinkedHashSet<>(256); /** * 在给定的bean name下,将存在的对象作为单例注册在工厂中 * 给定的实例应该是完全初始化;工厂不执行任何初始化回调(特别是,他不会调用InitializingBean的 * afterPropertiesSet方法) * 给定的实例也不接收任何销毁回调(像DisposableBean的destroy方法) * 当在完整的BeanFactory运行时: * 如果你的bean需要接收初始化或者销毁的回调,注册一个bean definition替代一个存在的实例 * 通常此方法在工厂配置时被调用,也能在运行时单例注册时被调用。 * 作为结果,工厂的实现应该同步单例的访问;如果支持BeanFactory的单例的延迟初始化就不得不这样做 * @param beanName the name of the bean * @param singletonObject the existing singleton object * @throws IllegalStateException */ @Override public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { Assert.notNull(beanName, "Bean name must not be null"); Assert.notNull(singletonObject, "Singleton object must not be null"); synchronized (this.singletonObjects) { Object oldObject = this.singletonObjects.get(beanName); //不能注册两次 if (oldObject != null) { throw new IllegalStateException("Could not register object [" + singletonObject + "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound"); } //进入这个方法 addSingleton(beanName, singletonObject); } } /** * Add the given singleton object to the singleton cache of this factory. * <p>To be called for eager registration of singletons. * 添加给定单例对象到工厂的单例缓存中 * 用来被提早注册的单例调用 * @param beanName the name of the bean * @param singletonObject the singleton object */ protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { //singletonObjects是一个ConcurrentHashMap //用来缓存单例对象 this.singletonObjects.put(beanName, singletonObject); //singletonFactories是一个HashMap //里面缓存着单例工厂 this.singletonFactories.remove(beanName); //早期单例对象 //earlySingletonObjects是一个HashMap this.earlySingletonObjects.remove(beanName); //registeredSingletons是一个LinkedHashSet //被注册单例的集合,以注册的顺序包含着bean name this.registeredSingletons.add(beanName); } } }

这样AbstractRefreshableWebApplicationContext中的postProcessBeanFactory方法就分析完了

 

参考: https://www.cnblogs.com/feng-jq/p/10282260.html

网友评论