`
jinnianshilongnian
  • 浏览: 21505208 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2418798
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3008953
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5639578
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259965
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597402
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250249
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5859076
Group-logo
跟我学Nginx+Lua开...
浏览量:702309
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785274
社区版块
存档分类
最新评论

Spring开闭原则的表现-BeanPostProcessor扩展点-2

阅读更多

 

 

上接Spring提供的BeanPostProcessor的扩展点-1继续分析。

 


四、BeanPostProcessor接口及回调方法图


 从图中我们可以看出一共五个接口,共十个回调方法,即十个扩展点,但我们之前的文章只分析了其中八个,另外两个稍候也会解析一下是干什么的。

 

===================================================================

===================================================================

五、五个接口十个扩展点解析

1InstantiationAwareBeanPostProcessor:实例化Bean后置处理器(继承BeanPostProcessor

postProcessBeforeInstantiation :在实例化目标对象之前执行,可以自定义实例化逻辑,如返回一个代理对象等,3.1处执行;如果此处返回的Bean不为null将中断后续Spring创建Bean的流程,且只执行postProcessAfterInitialization回调方法,如当AbstractAutoProxyCreator的实现者注册了TargetSourceCreator(创建自定义的TargetSource)将改变执行流程,不注册TargetSourceCreator我们默认使用的是SingletonTargetSource(即AOP代理直接保证目标对象),此处我们还可以使用如ThreadLocalTargetSource(线程绑定的Bean)、CommonsPoolTargetSource(实例池的Bean)等等,大家可以去spring官方文档了解TargetSource详情;

postProcessAfterInitialization : Bean实例化完毕后执行的后处理操作,所有初始化逻辑、装配逻辑之前执行,如果返回false将阻止其他的InstantiationAwareBeanPostProcessorpostProcessAfterInstantiation的执行,(3.2和(9.1处执行;在此处可以执行一些初始化逻辑或依赖装配逻辑;

postProcessPropertyValues :完成其他定制的一些依赖注入和依赖检查等,如AutowiredAnnotationBeanPostProcessor执行@Autowired注解注入,CommonAnnotationBeanPostProcessor执行@Resource等注解的注入,PersistenceAnnotationBeanPostProcessor执行@ PersistenceContextJPA注解的注入,RequiredAnnotationBeanPostProcessor执行@ Required注解的检查等等,9.3处执行;

 

2MergedBeanDefinitionPostProcessor:合并Bean定义后置处理器         (继承BeanPostProcessor

postProcessMergedBeanDefinition:执行Bean定义的合并,在7.1处执行,且在实例化完Bean之后执行;

 

3SmartInstantiationAwareBeanPostProcessor:智能实例化Bean后置处理器(继承InstantiationAwareBeanPostProcessor

predictBeanType:预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null;当你调用BeanFactory.getType(name)时当通过Bean定义无法得到Bean类型信息时就调用该回调方法来决定类型信息;BeanFactory.isTypeMatch(name, targetType)用于检测给定名字的Bean是否匹配目标类型(如在依赖注入时需要使用);

determineCandidateConstructors:检测Bean的构造器,可以检测出多个候选构造器,再有相应的策略决定使用哪一个,如AutowiredAnnotationBeanPostProcessor实现将自动扫描通过@Autowired/@Value注解的构造器从而可以完成构造器注入,请参考【第十二章】零配置 之12.2 注解实现Bean依赖注入 ——跟我学spring3 6.2.2.1处执行;

getEarlyBeanReference:当正在创建A时,A依赖B,此时通过(8A作为ObjectFactory放入单例工厂中进行early expose,此处B需要引用A,但A正在创建,从单例工厂拿到ObjectFactory(其通过getEarlyBeanReference获取及早暴露Bean),从而允许循环依赖,此时AspectJAwareAdvisorAutoProxyCreator(完成xml风格的AOP配置(<aop:config>)将目标对象(A)包装到AOP代理对象)或AnnotationAwareAspectJAutoProxyCreator(完成@Aspectj注解风格(<aop:aspectj-autoproxy> @Aspect)将目标对象(A)包装到AOP代理对象),其返回值将替代原始的Bean对象,即此时通过early reference能得到正确的代理对象,8.1处实施;如果此处执行了,10.3.3处的AspectJAwareAdvisorAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreatorpostProcessAfterInitialization将不执行,即这两个回调方法是二选一的;

 

4BeanPostProcessorBean后置处理器

postProcessBeforeInitialization:实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务,如BeanValidationPostProcessor完成JSR-303 @Valid注解Bean验证,InitDestroyAnnotationBeanPostProcessor完成@PostConstruct注解的初始化方法调用,ApplicationContextAwareProcessor完成一些Aware接口的注入(如EnvironmentAwareResourceLoaderAwareApplicationContextAware),其返回值将替代原始的Bean对象;10.2处执行;

postProcessAfterInitialization:实例化、依赖注入、初始化完毕时执行,如AspectJAwareAdvisorAutoProxyCreator(完成xml风格的AOP配置(<aop:config>)的目标对象包装到AOP代理对象)、AnnotationAwareAspectJAutoProxyCreator(完成@Aspectj注解风格(<aop:aspectj-autoproxy> @Aspect)的AOP配置的目标对象包装到AOP代理对象),其返回值将替代原始的Bean对象;10.3.3处执行;此处需要参考getEarlyBeanReference

 

5DestructionAwareBeanPostProcessor:销毁Bean后置处理器(继承BeanPostProcessor

postProcessBeforeDestruction:销毁后处理回调方法,该回调只能应用到单例Bean,如InitDestroyAnnotationBeanPostProcessor完成@PreDestroy注解的销毁方法调用;12.1.1处执行。

 

===================================================================

===================================================================

六、内置的一些BeanPostProcessor


 部分内置的BeanPostProcessor

此图只有内置的一部分。

 

1、ApplicationContextAwareProcessor

容器启动时会自动注册。注入那些实现ApplicationContextAwareMessageSourceAwareResourceLoaderAwareEnvironmentAware

EmbeddedValueResolverAwareApplicationEventPublisherAware标识接口的Bean需要的相应实例,在postProcessBeforeInitialization回调方法中进行实施,即10.2处实施。

 

2CommonAnnotationBeanPostProcessor

CommonAnnotationBeanPostProcessor继承InitDestroyAnnotationBeanPostProcessor,当在配置文件有<context:annotation-config><context:component-scan>会自动注册。

 

提供对JSR-250规范注解的支持@javax.annotation.Resource@javax.annotation.PostConstruct@javax.annotation.PreDestroy等的支持。

 

2.1、通过@Resource注解进行依赖注入:

    postProcessPropertyValues:通过此回调进行@Resource注解的依赖注入;9.3处实施;

2.2、用于执行@PostConstruct @PreDestroy 注解的初始化和销毁方法的扩展点:

    postProcessBeforeInitialization()将会调用bean@PostConstruct方法;10.2处实施;

    postProcessBeforeDestruction()将会调用单例 Bean@PreDestroy方法(此回调方法会在容器销毁时调用),12.1.1处实施。

 

详见【第十二章】零配置 之 12.2 注解实现Bean依赖注入 ——跟我学spring3JSR-250注解部分。


3AutowiredAnnotationBeanPostProcessor

当在配置文件有<context:annotation-config><context:component-scan>会自动注册。

 

提供对JSR-330规范注解的支持和Spring自带注解的支持。

 

3.1Spring自带注解的依赖注入支持,@Autowired@Value

    determineCandidateConstructors :决定候选构造器;详见【12.2中的构造器注入】;6.2.2.1处实施;

postProcessPropertyValues :进行依赖注入;详见【12.2中的字段注入和方法参数注入】;9.3处实施;

3.2、对JSR-330规范注解的依赖注入支持,@Inject

    2.1类似只是查找使用的注解不一样;

 

详见【第十二章】零配置 之 12.2 注解实现Bean依赖注入 ——跟我学spring3Spring自带依赖注入注解和 JSR-330注解部分。


4RequiredAnnotationBeanPostProcessor

当在配置文件有<context:annotation-config><context:component-scan>会自动注册。

 

4.1、提供对@ Required注解的方法进行依赖检查支持:

    postProcessPropertyValues:如果检测到没有进行依赖注入时抛出BeanInitializationException异常;9.3处实施;

 

详见【第十二章】零配置 之 12.2 注解实现Bean依赖注入 ——跟我学spring3@Required:依赖检查


5PersistenceAnnotationBeanPostProcessor

当在配置文件有<context:annotation-config><context:component-scan>会自动注册。

 

5.1、通过对JPA @ javax.persistence.PersistenceUnit@ javax.persistence.PersistenceContext注解进行依赖注入的支持;

    postProcessPropertyValues : 根据@PersistenceUnit/@PersistenceContext进行EntityManagerFactoryEntityManager的支持;


6AbstractAutoProxyCreator

AspectJAwareAdvisorAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreator都是继承AbstractAutoProxyCreatorAspectJAwareAdvisorAutoProxyCreator提供对(<aop:config>)声明式AOP的支持,AnnotationAwareAspectJAutoProxyCreator提供对(<aop:aspectj-autoproxy>)注解式(@AspectJAOP的支持,因此只需要分析AbstractAutoProxyCreator即可。

 

当使用<aop:config>配置时自动注册AspectJAwareAdvisorAutoProxyCreator,而使用<aop:aspectj-autoproxy>时会自动注册AnnotationAwareAspectJAutoProxyCreator

 

6.1predictBeanType:预测Bean的类型,如果目标对象被AOP代理对象包装,此处将返回AOP代理对象的类型;

public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
		Object cacheKey = getCacheKey(beanClass, beanName);
		return this.proxyTypes.get(cacheKey); //获取代理对象类型,可能返回null
}

6.2postProcessBeforeInstantiation

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
	//1、得到一个缓存的唯一key(根据beanClass和beanName生成唯一key)
	Object cacheKey = getCacheKey(beanClass, beanName);
	//2、如果当前targetSourcedBeans(通过自定义TargetSourceCreator创建的TargetSource)不包含cacheKey
	if (!this.targetSourcedBeans.contains(cacheKey)) {
		//2.1、advisedBeans(已经被增强的Bean,即AOP代理对象)中包含当前cacheKey或nonAdvisedBeans(不应该被增强的Bean)中包含当前cacheKey 返回null,即走Spring默认流程
		if (this.advisedBeans.contains(cacheKey) || this.nonAdvisedBeans.contains(cacheKey)) {
			return null;
		}
		//2.2、如果是基础设施类(如Advisor、Advice、AopInfrastructureBean的实现)不进行处理
		//2.2、shouldSkip 默认false,可以生成子类覆盖,如AspectJAwareAdvisorAutoProxyCreator覆盖	(if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) return true;  即如果是自己就跳过)
		if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
			this.nonAdvisedBeans.add(cacheKey);//在不能增强的Bean列表缓存当前cacheKey
			return null;
		}
	}

	//3、开始创建AOP代理对象
	//3.1、配置自定义的TargetSourceCreator进行TargetSource创建
	TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
	if (targetSource != null) {
		//3.2、如果targetSource不为null 添加到targetSourcedBeans缓存,并创建AOP代理对象
		this.targetSourcedBeans.add(beanName);
		// specificInterceptors即增强(包括前置增强、后置增强等等)
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
		//3.3、创建代理对象
		Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
		//3.4、将代理类型放入proxyTypes从而允许后续的predictBeanType()调用获取
		this.proxyTypes.put(cacheKey, proxy.getClass());
		return proxy;
	}
	return null;
}

  从如上代码可以看出,当我们配置TargetSourceCreator进行自定义TargetSource创建时,会创建代理对象并中断默认Spring创建流程。

 

6.3getEarlyBeanReference

//获取early Bean引用(只有单例Bean才能回调该方法)
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
	Object cacheKey = getCacheKey(bean.getClass(), beanName);
	//1、将cacheKey添加到earlyProxyReferences缓存,从而避免多次重复创建
	this.earlyProxyReferences.add(cacheKey);
	//2、包装目标对象到AOP代理对象(如果需要)
	return wrapIfNecessary(bean, beanName, cacheKey);
}
 

6.4postProcessAfterInitialization

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
	if (bean != null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		//1、如果之前调用过getEarlyBeanReference获取包装目标对象到AOP代理对象(如果需要),则不再执行
		if (!this.earlyProxyReferences.contains(cacheKey)) {
			//2、包装目标对象到AOP代理对象(如果需要)
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}

 

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	if (this.targetSourcedBeans.contains(beanName)) {//通过TargetSourceCreator进行自定义TargetSource不需要包装
		return bean;
	}
	if (this.nonAdvisedBeans.contains(cacheKey)) {//不应该被增强对象不需要包装
		return bean;
	}
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {//基础设施/应该skip的不需要保证
		this.nonAdvisedBeans.add(cacheKey);
		return bean;
	}

	// 如果有增强就执行包装目标对象到代理对象
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {
		this.advisedBeans.add(cacheKey);//将cacheKey添加到已经被增强列表,防止多次增强
		Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));//创建代理对象
		this.proxyTypes.put(cacheKey, proxy.getClass());//缓存代理类型
		return proxy;
	}
	this.nonAdvisedBeans.add(cacheKey);
	return bean;
}
  

从如上流程可以看出 getEarlyBeanReferencepostProcessAfterInitialization是二者选一的,而且单例Bean目标对象只能被增强一次,而原型Bean目标对象可能被包装多次。

 

7BeanValidationPostProcessor

默认不自动注册,Spring3.0开始支持。

 

提供对JSR-303验证规范支持。

 

根据afterInitializationfalse/true决定调用postProcessBeforeInitializationpostProcessAfterInitialization来通过JSR-303规范验证Bean,默认false


8MethodValidationPostProcessor

Spring3.1开始支持,且只支持Hibernate Validator 4.2及更高版本,从Spring 3.2起可能将采取自动检测Bean Validation 1.1兼容的提供商且自动注册(Bean Validation 1.1 (JSR-349)正处于草案阶段,它将提供方法级别的验证,提供对方法级别的验证),目前默认不自动注册。

 

Bean Validation 1.1草案请参考http://jcp.org/en/jsr/detail?id=349    http://beanvalidation.org/

 

提供对方法参数/方法返回值的进行验证(即前置条件/后置条件的支持),通过JSR-303注解验证,使用方式如:

public @NotNull Object myValidMethod(@NotNull String arg1, @Max(10) int arg2)

 

默认只对@org.springframework.validation.annotation.Validated注解的Bean进行验证,我们可以修改validatedAnnotationType为其他注解类型来支持其他注解验证。而且目前只支持Hibernate Validator实现,在未来版本可能支持其他实现。

 

有了这东西之后我们就不需要在进行如Assert.assertNotNull()这种前置条件/后置条件的判断了。


9ScheduledAnnotationBeanPostProcessor

当配置文件中有<task:annotation-driven>自动注册或@EnableScheduling自动注册。

 

提供对注解@Scheduled任务调度的支持。

 

postProcessAfterInitialization:通过查找Bean对象类上的@Scheduled注解来创建ScheduledMethodRunnable对象并注册任务调度方法(仅返回值为void且方法是无形式参数的才可以)。

 

可参考Spring官方文档的任务调度章节学习@Scheduled注解任务调度。


10AsyncAnnotationBeanPostProcessor

当配置文件中有<task:annotation-driven>自动注册或@EnableAsync自动注册。

 

提供对@ AsyncEJB3.1@javax.ejb.Asynchronous注解的异步调用支持。

 

postProcessAfterInitialization:通过ProxyFactory创建目标对象的代理对象,默认使用AsyncAnnotationAdvisor(内部使用AsyncExecutionInterceptor 通过AsyncTaskExecutor(继承TaskExecutor)通过submit提交异步任务)。

 

可参考Spring官方文档的异步调用章节学习@Async注解异步调用。


11ServletContextAwareProcessor

在使用Web容器时自动注册。

 

类似于ApplicationContextAwareProcessor,当你的Bean 实现了ServletContextAware/ ServletConfigAware会自动调用回调方法注入ServletContext/ ServletConfig

 

===================================================================

===================================================================

七、BeanPostProcessor如何注册

1、如ApplicationContextAwareProcessor会在ApplicationContext容器启动时自动注册,而CommonAnnotationBeanPostProcessorAutowiredAnnotationBeanPostProcessor会在当你使用<context:annotation-config><context:component-scan>配置时自动注册。

2、只要将BeanPostProcessor注册到容器中,Spring会在启动时自动获取并注册。

 

===================================================================

===================================================================

八、BeanPostProcessor的执行顺序

1、如果使用BeanFactory实现,非ApplicationContext实现,BeanPostProcessor执行顺序就是添加顺序。

 

2、如果使用的是AbstractApplicationContext(实现了ApplicationContext)的实现,则通过如下规则指定顺序。

2.1PriorityOrdered(继承了Ordered),实现了该接口的BeanPostProcessor会在第一个顺序注册,标识高优先级顺序,即比实现Ordered的具有更高的优先级;

2.2Ordered,实现了该接口的BeanPostProcessor会第二个顺序注册;

 

int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;//最高优先级

int LOWEST_PRECEDENCE = Integer.MAX_VALUE;//最低优先级

 

即数字越小优先级越高,数字越大优先级越低,如0(高优先级)——1000(低优先级)

 

2.3、无序的,没有实现Ordered/ PriorityOrdered的会在第三个顺序注册;

2.4、内部Bean后处理器,实现了MergedBeanDefinitionPostProcessor接口的是内部Bean PostProcessor,将在最后且无序注册。

 

 

3、接下来我们看看内置的BeanPostProcessor执行顺序

 

//1注册实现了PriorityOrdered接口的BeanPostProcessor

 

//2注册实现了Ordered接口的BeanPostProcessor

AbstractAutoProxyCreator              实现了Orderedorder = Ordered.LOWEST_PRECEDENCE

MethodValidationPostProcessor          实现了OrderedLOWEST_PRECEDENCE

ScheduledAnnotationBeanPostProcessor   实现了OrderedLOWEST_PRECEDENCE

AsyncAnnotationBeanPostProcessor      实现了Orderedorder = Ordered.LOWEST_PRECEDENCE

 

//3注册无实现任何接口的BeanPostProcessor

BeanValidationPostProcessor            无序

ApplicationContextAwareProcessor       无序

ServletContextAwareProcessor          无序

 

//3 注册实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor,且按照实现了Ordered的顺序进行注册,没有实现Ordered的默认为Ordered.LOWEST_PRECEDENCE

PersistenceAnnotationBeanPostProcessor  实现了PriorityOrderedOrdered.LOWEST_PRECEDENCE - 4

AutowiredAnnotationBeanPostProcessor   实现了PriorityOrderedorder = Ordered.LOWEST_PRECEDENCE - 2

RequiredAnnotationBeanPostProcessor    实现了PriorityOrderedorder = Ordered.LOWEST_PRECEDENCE - 1

CommonAnnotationBeanPostProcessor    实现了PriorityOrderedOrdered.LOWEST_PRECEDENCE

 

从上到下顺序执行,如果order相同则我们应该认为同序(谁先执行不确定,其执行顺序根据注册顺序决定)。

 

===================================================================

===================================================================

九、完成Spring事务处理时自我调用的解决方案及一些实现方式的分析分析

场景请先参考请参考Spring事务处理时自我调用的解决方案及一些实现方式的风险中的3.3、通过BeanPostProcessor 在目标对象中注入代理对象。

 

 

分析:


 

 

问题出现在59处:

 

5、使用步骤1处注册的SingletonFactoryObjectFactory.getObject() 使用AnnotationAwareAspectJAutoProxyCreatorgetEarlyBeanReference获取循环引用Bean),因此此处将返回A目标对象的代理对象;

 

9、此处调用AnnotationAwareAspectJAutoProxyCreatorpostProcessAfterInitialization,但发现之前调用过AnnotationAwareAspectJAutoProxyCreatorgetEarlyBeanReference获取代理对象,此处不再创建代理对象,而是直接返回目标对象,因此使用InjectBeanSelfProcessor不能注入代理对象;但此时的Spring容器中的A已经是代理对象了,因此我使用了从上下文重新获取A代理对象的方式注入(context.getBean(beanName))。

 

此处的getEarlyBeanReferencepostProcessAfterInitialization为什么是二者选一的请参考之前介绍的AbstractAutoProxyCreator

 

到此问题我们分析完毕,实际项目中的循环依赖应该尽量避免,这违反了“无环依赖原则”。

 

 

 

下一篇我将介绍一些内置BeanPostProcessor的使用和自定义一些自己的BeanPostProcessor来更好的理解这些扩展点。

19
5
分享到:
评论
4 楼 zb604501693 2019-06-27  
到现在我都认为这篇文章是比较经典的,但是说实话,看懂的人真的不多,除非他看懂了spring IOC的整个实例化和初始化过程,包括aop部分(当然aop是基于ioc 后置处理器实现的)
3 楼 jinnianshilongnian 2012-04-27  
yingzhor 写道
文章太长了,我也没细看。 我就是传说中浮躁的人。

不过请教一个问题。
我自己开发一个annotation和一个配套的BeanPostProcessor 来实现一些我定义的注入功能。

如果我只使用 RootWebApplicationContext 一个IoC上下文(保存在ServletContext里的这个)的话,这没有问题。
问题是,我现在要用SpringMVC框架,势必我还需要那个Request里面的上下文,我要存放Controller嘛, 这样的话,我的BeanPostProcessor 应该放在哪里配置呢?

如果在 spring-mvc.xml 里面的话,只能对ControllerBean起作用。
如果在 spring-root.xml 里面的话,只能对ServiceBean,DaoBean起作用。

你碰到过这样的情况没? 如果是你,你怎么做啊。


文章太长说明我写的不好,以后要尽量短小。

1、如果只对ServiceBean,DaoBean 放在spring-root.xml 即可

2、如果只对ControllerBean,放在spring-mvc.xml 即可

3、如果对ControllerBean、ServiceBean,DaoBean都起作用,两边都得放(因为是两个不同的上下文)

protected WebApplicationContext initWebApplicationContext() {
        //ROOT上下文(ContextLoaderListener加载的)
		WebApplicationContext rootContext =
				WebApplicationContextUtils.getWebApplicationContext(getServletContext());
		WebApplicationContext wac = null;
		if (this.webApplicationContext != null) {
			// 1、在创建该Servlet注入的上下文
			wac = this.webApplicationContext;
			if (wac instanceof ConfigurableWebApplicationContext) {
				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
				if (!cwac.isActive()) {
					if (cwac.getParent() == null) {
						cwac.setParent(rootContext);
					}
					configureAndRefreshWebApplicationContext(cwac);
				}
			}
		}
		if (wac == null) {
             //2、查找已经绑定的上下文
			wac = findWebApplicationContext();
		}
		if (wac == null) {
             //3、如果没有找到相应的上下文,并指定父亲为ContextLoaderListener
			wac = createWebApplicationContext(rootContext);
		}
		if (!this.refreshEventReceived) {
             //4、刷新上下文(执行一些初始化)
			onRefresh(wac);
		}
		if (this.publishContext) {
			// Publish the context as a servlet context attribute.
			String attrName = getServletContextAttributeName();
			getServletContext().setAttribute(attrName, wac);
			//省略部分代码
		}
		return wac;
	}

如上代码的第三步创建了SpringMVC的上下文 并只对ContextLoaderListener为根
2 楼 yingzhor 2012-04-27  
文章太长了,我也没细看。 我就是传说中浮躁的人。

不过请教一个问题。
我自己开发一个annotation和一个配套的BeanPostProcessor 来实现一些我定义的注入功能。

如果我只使用 RootWebApplicationContext 一个IoC上下文(保存在ServletContext里的这个)的话,这没有问题。
问题是,我现在要用SpringMVC框架,势必我还需要那个Request里面的上下文,我要存放Controller嘛, 这样的话,我的BeanPostProcessor 应该放在哪里配置呢?

如果在 spring-mvc.xml 里面的话,只能对ControllerBean起作用。
如果在 spring-root.xml 里面的话,只能对ServiceBean,DaoBean起作用。

你碰到过这样的情况没? 如果是你,你怎么做啊。
1 楼 研磨struts2 2012-04-21  
文章太长了

相关推荐

    spring框架3.0.0---api

    其次,Spring 3.0.0对AOP(面向切面编程)进行了扩展,提供了更多的切面编程模型。AOP允许开发者将关注点分离,如日志记录、事务管理等,可以编写一次,然后在整个应用程序中统一应用。Spring的`@Aspect`注解定义了...

    Spring-Reference_zh_CN(Spring中文参考手册)

    3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.1.1. 使用BeanPostProcessor的Hello World示例 3.7.1.2. RequiredAnnotationBeanPostProcessor示例 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7....

    java学习之spring2.0

    - **Bean的高级功能**:如bean的继承、FactoryBean、BeanPostProcessor和BeanFactoryPostProcessor等,增强了Bean的灵活性和扩展性。 4. **整合其他技术** - **MVC框架**:Spring MVC提供了模型-视图-控制器的...

    详解使用Spring的BeanPostProcessor优雅的实现工厂模式

    这种方式简单直接,但当需要添加新的handler时,需要修改现有代码,违背了开闭原则。 2. 动态工厂:例如HandlerService2,通过传入Class对象来动态实例化handler。这种方式更加灵活,可以避免修改原有代码,但可能...

    spring杂谈 作者zhang KaiTao

    BeanPostProcessor接口是Spring中实现开闭原则的一个重要工具,允许开发者在Spring容器初始化Bean前后进行自定义操作,增强了框架的可扩展性。作者探讨了如何利用BeanPostProcessor实现特定的业务逻辑,以及在两个...

    spring详细介绍

    Spring还提出了开闭原则的扩展点,**BeanPostProcessor** 是Spring提供的一个扩展接口,它允许开发者在Spring容器实例化Bean之后,初始化Bean之前以及初始化Bean之后这两个时机来对Bean进行干预。开发者可以通过实现...

    SPRING技术内幕_深入解析SPRING架构与设计原理

    知识点六:Spring框架的扩展性 Spring框架提供了很好的扩展机制。开发者可以自定义AOP的切面,通过实现BeanPostProcessor和BeanFactoryPostProcessor来自定义Bean的创建过程。另外,Spring允许开发者通过XML或者注解...

    spring chm文档

    3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. ApplicationContext 3.8.1. 利用MessageSource实现国际化 ...

    spring 杂谈,求扩散

    3. **BeanPostProcessor**:这是Spring的一个扩展点,它允许在bean初始化前后进行自定义处理。通过实现这个接口,开发者可以添加额外的行为,如属性注入、初始化逻辑等,遵循开闭原则,增强了框架的灵活性。 4. **...

    spring杂谈

    3. **BeanPostProcessor**:BeanPostProcessor是Spring中实现开闭原则的一个典型例子,它提供了一个扩展点,允许用户在bean初始化前后执行自定义逻辑,增强了Spring容器的灵活性。 4. **IoC/DI理解**:IoC...

    Spring 2.0 开发参考手册

    3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. ApplicationContext 3.8.1. 利用MessageSource实现国际化 ...

    Spring中文帮助文档

    3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. The ApplicationContext 3.8.1. BeanFactory 还是 ...

    Spring API

    3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. The ApplicationContext 3.8.1. BeanFactory 还是 ...

    spring常见的一些面试题

    ### Spring 框架及其优势 1. **Spring框架简介**:Spring是一个开源的Java应用框架,主要用于简化企业级应用的...以上内容涵盖了Spring框架中的一些基础且重要的知识点,希望对准备面试或学习Spring的朋友有所帮助。

    SpringFramework常见知识点.md

    #### 十一、Spring 的扩展点 1. **BeanPostProcessor**:在 Bean 初始化前后进行处理。 2. **BeanFactoryPostProcessor**:在所有的 Bean 定义加载后,但在任何 Bean 实例被创建之前修改 BeanFactory。 3. **...

    探秘Spring框架解决循环依赖的高效策略

    为了进一步扩展这个机制,开发者可以通过自定义BeanPostProcessor或者AOP配置来实现特定的处理逻辑,例如添加更多的检查或者特殊处理逻辑。同时,遵循良好的设计模式,如单一职责原则、依赖倒置原则等,可以有效地...

    soring02.zip

    8. **容器扩展点**:Spring提供了多种扩展点,如Bean后处理器(BeanPostProcessor)、Bean工厂后处理器(BeanFactoryPostProcessor),允许开发者自定义Bean的初始化和销毁逻辑。 这个“soring02”可能包含了一个或...

Global site tag (gtag.js) - Google Analytics