论坛首页 Java企业应用论坛

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

浏览 26168 次
该帖已经被评为精华帖
作者 正文
   发表时间:2012-04-20   最后修改:2012-04-20

 

 

上接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如何注册

1ApplicationContextAwareProcessor会在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来更好的理解这些扩展点。

  • 大小: 28.9 KB
  • 大小: 30.6 KB
  • 大小: 50.6 KB
   发表时间:2012-04-20  
好文,多谢分享
0 请登录后投票
   发表时间:2012-04-21  
grzrt 写道
支持学习精神

谢谢兄弟支持,希望一起来探讨,对BeanPostProcessor你有什么观点吗?
0 请登录后投票
   发表时间:2012-04-21  
虽然不懂,但是还是支持分享的精神
0 请登录后投票
   发表时间:2012-04-21  
Sunyx 写道
虽然不懂,但是还是支持分享的精神

希望能一起探讨,学习是一种信仰,能使我们进步 
0 请登录后投票
   发表时间:2012-04-21  
spring系列很不错
0 请登录后投票
   发表时间:2012-04-21  
caoxudong818 写道
spring系列很不错

欢迎兄弟一起来分享spring相关的技术及一些常见问题
0 请登录后投票
   发表时间:2012-04-21  
问一个问题:

我想扩展MappingJacksonHttpMessageConverter(或者自己实现HttpMessageConverter用别的Json处理lib来实现)在方法上使用注解@ResponseBody 来返回json。

但是遇到一个问题,我们返回的对象,比如User,是有很多属性的,并不需要序列化所有的属性,而且是每个方法上不一样的(所以不能直接在实体上写Jackson的ignore注解来实现),想在controller层的方法上加个自定义注解来实现,但是HttpMessageConverter这个接口,并没有传入任何当前的handlerMethod,所以也就无法获取当前方法上的我自己定义的注解。

不知道有没有什么好的方案来实现这样的功能?
0 请登录后投票
   发表时间:2012-04-21   最后修改:2012-04-21
guofengcn 写道
问一个问题:

我想扩展MappingJacksonHttpMessageConverter(或者自己实现HttpMessageConverter用别的Json处理lib来实现)在方法上使用注解@ResponseBody 来返回json。

但是遇到一个问题,我们返回的对象,比如User,是有很多属性的,并不需要序列化所有的属性,而且是每个方法上不一样的(所以不能直接在实体上写Jackson的ignore注解来实现),想在controller层的方法上加个自定义注解来实现,但是HttpMessageConverter这个接口,并没有传入任何当前的handlerMethod,所以也就无法获取当前方法上的我自己定义的注解。

不知道有没有什么好的方案来实现这样的功能?


customModelAndViewResolvers倒是可以实现这个功能,但是感觉不太方便
0 请登录后投票
   发表时间:2012-04-21  
guofengcn 写道
guofengcn 写道
问一个问题:

我想扩展MappingJacksonHttpMessageConverter(或者自己实现HttpMessageConverter用别的Json处理lib来实现)在方法上使用注解@ResponseBody 来返回json。

但是遇到一个问题,我们返回的对象,比如User,是有很多属性的,并不需要序列化所有的属性,而且是每个方法上不一样的(所以不能直接在实体上写Jackson的ignore注解来实现),想在controller层的方法上加个自定义注解来实现,但是HttpMessageConverter这个接口,并没有传入任何当前的handlerMethod,所以也就无法获取当前方法上的我自己定义的注解。

不知道有没有什么好的方案来实现这样的功能?


customModelAndViewResolvers倒是可以实现这个功能,但是感觉不太方便



每个方法上不一样——是不是可以自己wrap一个JsonTransformerWrap,传递一个Object target,然后根据每个方法,再set一个List标示想output哪些properties,

然后用这个JsonTransformerWrap去做json output

PS:如果是动态语言,就更容易实现些,可以在运行时候动态修改/删除User的properties
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics