here's my config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com">
<context:include-filter type="assignable" expression="com.coc.frmwk.cmd.Command"/>
<context:include-filter type="assignable" expression="com.coc.apps.sample.dao.S开发者_JS百科ampleDAO"/>
</context:component-scan>
<bean id="myPostProcessor" class="com.coc.frmwrk.processors.MyPostProcessor">
</beans>
I know that when using component-scan, the default scope that will be assigned to the beans is "singleton" unless it's specified otherwise in the xml configuration or using the annotation @Scope, that's cool, but since i've figured out that in my application all the beans implementing a specific interface (com.coc.frmwk.cmd.Command) need to have their scope set to "prototype", so i added a class "ScopeResolver" that implements ScopeMetaDataResolver and i made this little modification to my config.xml so that the container takes into account my scope resolver :
<context:component-scan base-package="com" scope-resolver="com.coc.frmwk.processors.ScopeResolver">
My problem is that the BeanPostProcessor used to work perfectly, but it stops being called whenever i add the scope resolver ( context:component-scan base-package="com" scope-resolver="com.xxx.frmwk.processors.ScopeResolver" ) and it works again when i omit the stuff in bold.
Any idea on how to make The BeanPostProcessor works when the ScopeResolver is configured ? Thanks, Mehdi.
Edit: here's the content of my scope resolver
package com.coc.frmwk.processors;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ScopeMetadata;
import org.springframework.context.annotation.ScopeMetadataResolver;
import com.coc.frmwk.cmd.Command;
public class ScopeResolver implements ScopeMetadataResolver{
@SuppressWarnings("unchecked")
@Override
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
ScopeMetadata result = new ScopeMetadata();
Class c= null;
try {
c = Class.forName(definition.getBeanClassName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (Command.class.isAssignableFrom(c))
result.setScopeName("prototype");
else
result.setScopeName("singleton");
System.out.println("[Scope Resolver] " + definition.getBeanClassName() + "[" + result.getScopeName() + "]");
return result;
}
}
Edit2: I want to point out that the BeanPostProcessor is in fact being called, but apparently it works with all the beans except those having their scope changed by the ScopeMeteDataResolver.
The behavior you describe is the behavior I would expect. (At least at startup), the BeanPostProcessor
is called as soon as a bean is constructed, a prototype scoped bean is only constructed when it is requested. So if you don't use this bean anywhere the BeanPostProcessor
will not get called.
However judging from what you want you want to modify the recipe (the BeanDefinition
and not so much the created bean instance). For chancing the recipes you need to use a BeanFactoryPostProcessor
.
The difference is that a BeanPostProcessor
operates on bean instances where as the BeanFactoryPostProcessor
works on the bean creation recipes (the BeanDefinitions
).
I haven't found exactly how to solve the problem, but i did find a workaround, this might be useful for anyone having the same issue.
well instead of using a combination of BeanPostProcessor and a MetaDataScopeResolver, i decided to use a BeanFactoryPostProcessor that manages both the scope resolution and the bean processing.
here'ds the code of the BeanFactoryPostProcessor for anyone interested:
@Component
public class OaliaBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@SuppressWarnings("unchecked")
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
for(String beanName : beanFactory.getBeanDefinitionNames())
{
//Scope resolution
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
Class beanClass= null;
try {
beanClass = Class.forName(beanDefinition.getBeanClassName());
} catch (ClassNotFoundException e) {
// exception handling goes here
}
if (Command.class.isAssignableFrom(beanClass))
beanDefinition.setScope("prototype");
//Stuff that the BeanPostProcessor do go here
//..........
//..........
System.out.println("[Post Processing] " + beanName + " [" + beanDefinition.getScope() + "]");
}
}
}
精彩评论