- 浏览: 21505208 次
- 性别:
博客专栏
-
跟我学spring3
浏览量:2418798
-
Spring杂谈
浏览量:3008953
-
跟开涛学SpringMVC...
浏览量:5639578
-
Servlet3.1规范翻...
浏览量:259965
-
springmvc杂谈
浏览量:1597402
-
hibernate杂谈
浏览量:250249
-
跟我学Shiro
浏览量:5859076
-
跟我学Nginx+Lua开...
浏览量:702309
-
亿级流量网站架构核心技术
浏览量:785274
文章分类
- 全部博客 (329)
- 跟我学Nginx+Lua开发 (13)
- 跟我学spring (54)
- 跟开涛学SpringMVC (34)
- spring4 (16)
- spring杂谈 (50)
- springmvc杂谈 (22)
- 跟我学Shiro (26)
- shiro杂谈 (3)
- hibernate杂谈 (10)
- java开发常见问题分析 (36)
- 加速Java应用开发 (5)
- Servlet 3.1规范[翻译] (21)
- servlet3.x (2)
- websocket协议[翻译] (14)
- websocket规范[翻译] (1)
- java web (6)
- db (1)
- js & jquery & bootstrap (4)
- 非技术 (4)
- reminder[转载] (23)
- 跟叶子学把妹 (8)
- nginx (2)
- 架构 (19)
- flume架构与源码分析 (4)
最新评论
-
xxx不是你可以惹得:
认真看错误代码,有时候重启电脑就行了 醉了 我把数据库配置写死 ...
第十六章 综合实例——《跟我学Shiro》 -
dagger9527:
holyselina 写道您前面说到能获取调用是的参数数组,我 ...
【第六章】 AOP 之 6.6 通知参数 ——跟我学spring3 -
xxx不是你可以惹得:
Access denied for user 'root'@' ...
第十六章 综合实例——《跟我学Shiro》 -
dagger9527:
只有@AspectJ支持命名切入点,而Schema风格不支持命 ...
【第六章】 AOP 之 6.5 AspectJ切入点语法详解 ——跟我学spring3 -
dagger9527:
支持虽然会迟到,但永远不会缺席!
【第四章】 资源 之 4.3 访问Resource ——跟我学spring3
上接Spring提供的BeanPostProcessor的扩展点-1继续分析。
四、BeanPostProcessor接口及回调方法图
从图中我们可以看出一共五个接口,共十个回调方法,即十个扩展点,但我们之前的文章只分析了其中八个,另外两个稍候也会解析一下是干什么的。
===================================================================
===================================================================
五、五个接口十个扩展点解析
1、InstantiationAwareBeanPostProcessor:实例化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将阻止其他的InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation的执行,(3.2和(9.1处执行;在此处可以执行一些初始化逻辑或依赖装配逻辑;
postProcessPropertyValues :完成其他定制的一些依赖注入和依赖检查等,如AutowiredAnnotationBeanPostProcessor执行@Autowired注解注入,CommonAnnotationBeanPostProcessor执行@Resource等注解的注入,PersistenceAnnotationBeanPostProcessor执行@ PersistenceContext等JPA注解的注入,RequiredAnnotationBeanPostProcessor执行@ Required注解的检查等等,(9.3处执行;
2、MergedBeanDefinitionPostProcessor:合并Bean定义后置处理器 (继承BeanPostProcessor)
postProcessMergedBeanDefinition:执行Bean定义的合并,在(7.1处执行,且在实例化完Bean之后执行;
3、SmartInstantiationAwareBeanPostProcessor:智能实例化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,此时通过(8将A作为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处的AspectJAwareAdvisorAutoProxyCreator或AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization将不执行,即这两个回调方法是二选一的;
4、BeanPostProcessor:Bean后置处理器
postProcessBeforeInitialization:实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务,如BeanValidationPostProcessor完成JSR-303 @Valid注解Bean验证,InitDestroyAnnotationBeanPostProcessor完成@PostConstruct注解的初始化方法调用,ApplicationContextAwareProcessor完成一些Aware接口的注入(如EnvironmentAware、ResourceLoaderAware、ApplicationContextAware),其返回值将替代原始的Bean对象;(10.2处执行;
postProcessAfterInitialization:实例化、依赖注入、初始化完毕时执行,如AspectJAwareAdvisorAutoProxyCreator(完成xml风格的AOP配置(<aop:config>)的目标对象包装到AOP代理对象)、AnnotationAwareAspectJAutoProxyCreator(完成@Aspectj注解风格(<aop:aspectj-autoproxy> @Aspect)的AOP配置的目标对象包装到AOP代理对象),其返回值将替代原始的Bean对象;(10.3.3处执行;此处需要参考getEarlyBeanReference;
5、DestructionAwareBeanPostProcessor:销毁Bean后置处理器(继承BeanPostProcessor)
postProcessBeforeDestruction:销毁后处理回调方法,该回调只能应用到单例Bean,如InitDestroyAnnotationBeanPostProcessor完成@PreDestroy注解的销毁方法调用;(12.1.1处执行。
===================================================================
===================================================================
六、内置的一些BeanPostProcessor
部分内置的BeanPostProcessor
此图只有内置的一部分。
1、ApplicationContextAwareProcessor
容器启动时会自动注册。注入那些实现ApplicationContextAware、MessageSourceAware、ResourceLoaderAware、EnvironmentAware、
EmbeddedValueResolverAware、ApplicationEventPublisherAware标识接口的Bean需要的相应实例,在postProcessBeforeInitialization回调方法中进行实施,即(10.2处实施。
2、CommonAnnotationBeanPostProcessor
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依赖注入 ——跟我学spring3,JSR-250注解部分。
3、AutowiredAnnotationBeanPostProcessor
当在配置文件有<context:annotation-config>或<context:component-scan>会自动注册。
提供对JSR-330规范注解的支持和Spring自带注解的支持。
3.1、Spring自带注解的依赖注入支持,@Autowired和@Value:
determineCandidateConstructors :决定候选构造器;详见【12.2中的构造器注入】;(6.2.2.1处实施;
postProcessPropertyValues :进行依赖注入;详见【12.2中的字段注入和方法参数注入】;(9.3处实施;
3.2、对JSR-330规范注解的依赖注入支持,@Inject:
同2.1类似只是查找使用的注解不一样;
详见【第十二章】零配置 之 12.2 注解实现Bean依赖注入 ——跟我学spring3,Spring自带依赖注入注解和 JSR-330注解部分。
4、RequiredAnnotationBeanPostProcessor
当在配置文件有<context:annotation-config>或<context:component-scan>会自动注册。
4.1、提供对@ Required注解的方法进行依赖检查支持:
postProcessPropertyValues:如果检测到没有进行依赖注入时抛出BeanInitializationException异常;(9.3处实施;
详见【第十二章】零配置 之 12.2 注解实现Bean依赖注入 ——跟我学spring3,@Required:依赖检查。
5、PersistenceAnnotationBeanPostProcessor
当在配置文件有<context:annotation-config>或<context:component-scan>会自动注册。
5.1、通过对JPA @ javax.persistence.PersistenceUnit和@ javax.persistence.PersistenceContext注解进行依赖注入的支持;
postProcessPropertyValues : 根据@PersistenceUnit/@PersistenceContext进行EntityManagerFactory和EntityManager的支持;
6、AbstractAutoProxyCreator
AspectJAwareAdvisorAutoProxyCreator和AnnotationAwareAspectJAutoProxyCreator都是继承AbstractAutoProxyCreator,AspectJAwareAdvisorAutoProxyCreator提供对(<aop:config>)声明式AOP的支持,AnnotationAwareAspectJAutoProxyCreator提供对(<aop:aspectj-autoproxy>)注解式(@AspectJ)AOP的支持,因此只需要分析AbstractAutoProxyCreator即可。
当使用<aop:config>配置时自动注册AspectJAwareAdvisorAutoProxyCreator,而使用<aop:aspectj-autoproxy>时会自动注册AnnotationAwareAspectJAutoProxyCreator。
6.1、predictBeanType:预测Bean的类型,如果目标对象被AOP代理对象包装,此处将返回AOP代理对象的类型;
public Class<?> predictBeanType(Class<?> beanClass, String beanName) { Object cacheKey = getCacheKey(beanClass, beanName); return this.proxyTypes.get(cacheKey); //获取代理对象类型,可能返回null }
6.2、postProcessBeforeInstantiation:
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.3、getEarlyBeanReference
//获取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.4、postProcessAfterInitialization
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; }
从如上流程可以看出 getEarlyBeanReference和postProcessAfterInitialization是二者选一的,而且单例Bean目标对象只能被增强一次,而原型Bean目标对象可能被包装多次。
7、BeanValidationPostProcessor
默认不自动注册,Spring3.0开始支持。
提供对JSR-303验证规范支持。
根据afterInitialization是false/true决定调用postProcessBeforeInitialization或postProcessAfterInitialization来通过JSR-303规范验证Bean,默认false。
8、MethodValidationPostProcessor
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()这种前置条件/后置条件的判断了。
9、ScheduledAnnotationBeanPostProcessor
当配置文件中有<task:annotation-driven>自动注册或@EnableScheduling自动注册。
提供对注解@Scheduled任务调度的支持。
postProcessAfterInitialization:通过查找Bean对象类上的@Scheduled注解来创建ScheduledMethodRunnable对象并注册任务调度方法(仅返回值为void且方法是无形式参数的才可以)。
可参考Spring官方文档的任务调度章节学习@Scheduled注解任务调度。
10、AsyncAnnotationBeanPostProcessor
当配置文件中有<task:annotation-driven>自动注册或@EnableAsync自动注册。
提供对@ Async和EJB3.1的@javax.ejb.Asynchronous注解的异步调用支持。
postProcessAfterInitialization:通过ProxyFactory创建目标对象的代理对象,默认使用AsyncAnnotationAdvisor(内部使用AsyncExecutionInterceptor 通过AsyncTaskExecutor(继承TaskExecutor)通过submit提交异步任务)。
可参考Spring官方文档的异步调用章节学习@Async注解异步调用。
11、ServletContextAwareProcessor
在使用Web容器时自动注册。
类似于ApplicationContextAwareProcessor,当你的Bean 实现了ServletContextAware/ ServletConfigAware会自动调用回调方法注入ServletContext/ ServletConfig。
===================================================================
===================================================================
七、BeanPostProcessor如何注册
1、如ApplicationContextAwareProcessor会在ApplicationContext容器启动时自动注册,而CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor会在当你使用<context:annotation-config>或<context:component-scan>配置时自动注册。
2、只要将BeanPostProcessor注册到容器中,Spring会在启动时自动获取并注册。
===================================================================
===================================================================
八、BeanPostProcessor的执行顺序
1、如果使用BeanFactory实现,非ApplicationContext实现,BeanPostProcessor执行顺序就是添加顺序。
2、如果使用的是AbstractApplicationContext(实现了ApplicationContext)的实现,则通过如下规则指定顺序。
2.1、PriorityOrdered(继承了Ordered),实现了该接口的BeanPostProcessor会在第一个顺序注册,标识高优先级顺序,即比实现Ordered的具有更高的优先级;
2.2、Ordered,实现了该接口的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 实现了Ordered,order = Ordered.LOWEST_PRECEDENCE
MethodValidationPostProcessor 实现了Ordered,LOWEST_PRECEDENCE
ScheduledAnnotationBeanPostProcessor 实现了Ordered,LOWEST_PRECEDENCE
AsyncAnnotationBeanPostProcessor 实现了Ordered,order = Ordered.LOWEST_PRECEDENCE
//3注册无实现任何接口的BeanPostProcessor
BeanValidationPostProcessor 无序
ApplicationContextAwareProcessor 无序
ServletContextAwareProcessor 无序
//3 注册实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor,且按照实现了Ordered的顺序进行注册,没有实现Ordered的默认为Ordered.LOWEST_PRECEDENCE。
PersistenceAnnotationBeanPostProcessor 实现了PriorityOrdered,Ordered.LOWEST_PRECEDENCE - 4
AutowiredAnnotationBeanPostProcessor 实现了PriorityOrdered,order = Ordered.LOWEST_PRECEDENCE - 2
RequiredAnnotationBeanPostProcessor 实现了PriorityOrdered,order = Ordered.LOWEST_PRECEDENCE - 1
CommonAnnotationBeanPostProcessor 实现了PriorityOrdered,Ordered.LOWEST_PRECEDENCE
从上到下顺序执行,如果order相同则我们应该认为同序(谁先执行不确定,其执行顺序根据注册顺序决定)。
===================================================================
===================================================================
九、完成Spring事务处理时自我调用的解决方案及一些实现方式的分析分析
场景请先参考请参考Spring事务处理时自我调用的解决方案及一些实现方式的风险中的3.3、通过BeanPostProcessor 在目标对象中注入代理对象。
分析:
问题出现在5和9处:
5、使用步骤1处注册的SingletonFactory(ObjectFactory.getObject() 使用AnnotationAwareAspectJAutoProxyCreator的getEarlyBeanReference获取循环引用Bean),因此此处将返回A目标对象的代理对象;
9、此处调用AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization,但发现之前调用过AnnotationAwareAspectJAutoProxyCreator的getEarlyBeanReference获取代理对象,此处不再创建代理对象,而是直接返回目标对象,因此使用InjectBeanSelfProcessor不能注入代理对象;但此时的Spring容器中的A已经是代理对象了,因此我使用了从上下文重新获取A代理对象的方式注入(context.getBean(beanName))。
此处的getEarlyBeanReference和postProcessAfterInitialization为什么是二者选一的请参考之前介绍的AbstractAutoProxyCreator。
到此问题我们分析完毕,实际项目中的循环依赖应该尽量避免,这违反了“无环依赖原则”。
下一篇我将介绍一些内置BeanPostProcessor的使用和自定义一些自己的BeanPostProcessor来更好的理解这些扩展点。
评论
不过请教一个问题。
我自己开发一个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为根
不过请教一个问题。
我自己开发一个annotation和一个配套的BeanPostProcessor 来实现一些我定义的注入功能。
如果我只使用 RootWebApplicationContext 一个IoC上下文(保存在ServletContext里的这个)的话,这没有问题。
问题是,我现在要用SpringMVC框架,势必我还需要那个Request里面的上下文,我要存放Controller嘛, 这样的话,我的BeanPostProcessor 应该放在哪里配置呢?
如果在 spring-mvc.xml 里面的话,只能对ControllerBean起作用。
如果在 spring-root.xml 里面的话,只能对ServiceBean,DaoBean起作用。
你碰到过这样的情况没? 如果是你,你怎么做啊。
发表评论
-
一段Spring代码引起的调用绑定总结
2014-03-04 07:41 15379代码 @Component public class B ... -
一段Spring代码引起的调用绑定总结
2014-03-02 10:53 0代码 @Component public class ... -
Spring Cache抽象详解
2014-01-08 07:54 151098缓存简介 缓存,我的理解是:让数据更接近于使 ... -
Spring3.1新属性管理API:PropertySource、Environment、Profile
2014-01-07 08:05 72992Spring3.1提供了新的属性管理API,而且功能非常强 ... -
Spring3.1新属性管理API:PropertySource、Environment、Profile
2014-01-07 08:04 0Spring3.1提供了新的属性管理API,而且功能非常强 ... -
Spring动态部署Bean/Controller/Groovy Controller
2014-01-06 08:00 24466最近有好几个咨询如何动态部署Bean/动态部署Spring ... -
Spring4新特性——注解、脚本、任务、MVC等其他特性改进
2013-12-25 07:58 68895Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring4新特性——JSR310日期时间API的支持
2013-12-24 07:48 39469Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring3.1新属性管理API:PropertySource、Environment、Profile
2013-12-23 21:44 0Spring3.1提供了新的属性管理API,而且功能非常强 ... -
Spring4新特性——更好的Java泛型操作API
2013-12-23 07:43 42013Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring4新特性——Groovy Bean定义DSL
2013-12-19 07:33 37780Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring4新特性——Groovy Bean定义DSL
2013-12-18 20:53 0Spring4支持使用Groovy DSL来进行Bean定 ... -
Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC
2013-12-16 08:10 158131Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC
2013-12-15 10:51 0在之前的《跟我学SpringMVC》中的《第七章 注解式控 ... -
Spring4新特性——Web开发的增强
2013-12-14 08:12 270752Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring4新特性——核心容器的其他改进
2013-12-14 07:23 47765Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring4新特性——核心容器的其他改进
2013-12-13 22:54 311接上一篇《Spring4新特性——泛型限定式依赖注入》,接 ... -
Spring4新特性——泛型限定式依赖注入
2013-12-13 20:46 119576Spring4新特性——泛型限定式依赖注入 Spring ... -
Spring事务超时时间可能存在的错误认识
2013-12-06 09:36 476181、先看代码 1.1、spring-config.xml ... -
采用共享jar包部署struts2+spring集成项目会遇到的问题
2013-11-29 06:45 6356比如tomcat下边有个lib,放着我们需要的struts2 ...
相关推荐
其次,Spring 3.0.0对AOP(面向切面编程)进行了扩展,提供了更多的切面编程模型。AOP允许开发者将关注点分离,如日志记录、事务管理等,可以编写一次,然后在整个应用程序中统一应用。Spring的`@Aspect`注解定义了...
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....
- **Bean的高级功能**:如bean的继承、FactoryBean、BeanPostProcessor和BeanFactoryPostProcessor等,增强了Bean的灵活性和扩展性。 4. **整合其他技术** - **MVC框架**:Spring MVC提供了模型-视图-控制器的...
这种方式简单直接,但当需要添加新的handler时,需要修改现有代码,违背了开闭原则。 2. 动态工厂:例如HandlerService2,通过传入Class对象来动态实例化handler。这种方式更加灵活,可以避免修改原有代码,但可能...
BeanPostProcessor接口是Spring中实现开闭原则的一个重要工具,允许开发者在Spring容器初始化Bean前后进行自定义操作,增强了框架的可扩展性。作者探讨了如何利用BeanPostProcessor实现特定的业务逻辑,以及在两个...
Spring还提出了开闭原则的扩展点,**BeanPostProcessor** 是Spring提供的一个扩展接口,它允许开发者在Spring容器实例化Bean之后,初始化Bean之前以及初始化Bean之后这两个时机来对Bean进行干预。开发者可以通过实现...
知识点六:Spring框架的扩展性 Spring框架提供了很好的扩展机制。开发者可以自定义AOP的切面,通过实现BeanPostProcessor和BeanFactoryPostProcessor来自定义Bean的创建过程。另外,Spring允许开发者通过XML或者注解...
3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. ApplicationContext 3.8.1. 利用MessageSource实现国际化 ...
3. **BeanPostProcessor**:这是Spring的一个扩展点,它允许在bean初始化前后进行自定义处理。通过实现这个接口,开发者可以添加额外的行为,如属性注入、初始化逻辑等,遵循开闭原则,增强了框架的灵活性。 4. **...
3. **BeanPostProcessor**:BeanPostProcessor是Spring中实现开闭原则的一个典型例子,它提供了一个扩展点,允许用户在bean初始化前后执行自定义逻辑,增强了Spring容器的灵活性。 4. **IoC/DI理解**:IoC...
3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. ApplicationContext 3.8.1. 利用MessageSource实现国际化 ...
3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. The ApplicationContext 3.8.1. BeanFactory 还是 ...
3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. The ApplicationContext 3.8.1. BeanFactory 还是 ...
### Spring 框架及其优势 1. **Spring框架简介**:Spring是一个开源的Java应用框架,主要用于简化企业级应用的...以上内容涵盖了Spring框架中的一些基础且重要的知识点,希望对准备面试或学习Spring的朋友有所帮助。
#### 十一、Spring 的扩展点 1. **BeanPostProcessor**:在 Bean 初始化前后进行处理。 2. **BeanFactoryPostProcessor**:在所有的 Bean 定义加载后,但在任何 Bean 实例被创建之前修改 BeanFactory。 3. **...
为了进一步扩展这个机制,开发者可以通过自定义BeanPostProcessor或者AOP配置来实现特定的处理逻辑,例如添加更多的检查或者特殊处理逻辑。同时,遵循良好的设计模式,如单一职责原则、依赖倒置原则等,可以有效地...
8. **容器扩展点**:Spring提供了多种扩展点,如Bean后处理器(BeanPostProcessor)、Bean工厂后处理器(BeanFactoryPostProcessor),允许开发者自定义Bean的初始化和销毁逻辑。 这个“soring02”可能包含了一个或...