Fra*_*ois 46 spring annotations
使用XML配置的Spring bean工厂,我可以使用不同的参数轻松实例化同一个类的多个实例.我怎么能用注释做同样的事情?我想要这样的东西:
@Component(firstName="joe", lastName="smith")
@Component(firstName="mary", lastName="Williams")
public class Person { /* blah blah */ }
Run Code Online (Sandbox Code Playgroud)
Esp*_*pen 32
这是不可能的.你得到一个重复的例外.
在您的实现类中,这与配置数据相差甚远.
如果要使用注释,可以使用Java配置来配置类:
@Configuration
public class PersonConfig {
@Bean
public Person personOne() {
return new Person("Joe", "Smith");
}
@Bean
public Person personTwo() {
return new Person("Mary", "Williams");
}
}
Run Code Online (Sandbox Code Playgroud)
wax*_*wax 16
是的,您可以在自定义BeanFactoryPostProcessor实现的帮助下完成此操作.
这是一个简单的例子.
假设我们有两个组件.一个是对另一个的依赖.
第一部分:
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
public class MyFirstComponent implements InitializingBean{
private MySecondComponent asd;
private MySecondComponent qwe;
public void afterPropertiesSet() throws Exception {
Assert.notNull(asd);
Assert.notNull(qwe);
}
public void setAsd(MySecondComponent asd) {
this.asd = asd;
}
public void setQwe(MySecondComponent qwe) {
this.qwe = qwe;
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,此组件没有什么特别之处.它依赖于MySecondComponent的两个不同实例.
第二部分:
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
@Qualifier(value = "qwe, asd")
public class MySecondComponent implements FactoryBean {
public Object getObject() throws Exception {
return new MySecondComponent();
}
public Class getObjectType() {
return MySecondComponent.class;
}
public boolean isSingleton() {
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
这有点棘手.这里有两件事需要解释.第一个 - @Qualifier - 包含MySecondComponent bean名称的注释.这是标准的,但您可以自由实施.稍后你会看到原因.
第二件事是FactoryBean实现.如果bean实现了这个接口,那么它就是要创建一些其他实例.在我们的例子中,它使用MySecondComponent类型创建实例.
最棘手的部分是BeanFactoryPostProcessor实现:
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
Map<String, Object> map = configurableListableBeanFactory.getBeansWithAnnotation(Qualifier.class);
for(Map.Entry<String,Object> entry : map.entrySet()){
createInstances(configurableListableBeanFactory, entry.getKey(), entry.getValue());
}
}
private void createInstances(
ConfigurableListableBeanFactory configurableListableBeanFactory,
String beanName,
Object bean){
Qualifier qualifier = bean.getClass().getAnnotation(Qualifier.class);
for(String name : extractNames(qualifier)){
Object newBean = configurableListableBeanFactory.getBean(beanName);
configurableListableBeanFactory.registerSingleton(name.trim(), newBean);
}
}
private String[] extractNames(Qualifier qualifier){
return qualifier.value().split(",");
}
}
Run Code Online (Sandbox Code Playgroud)
它有什么作用?它遍历所有使用@Qualifier注释的bean,从注释中提取名称,然后手动创建具有指定名称的此类bean.
这是一个Spring配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="MyBeanFactoryPostProcessor"/>
<bean class="MySecondComponent"/>
<bean name="test" class="MyFirstComponent">
<property name="asd" ref="asd"/>
<property name="qwe" ref="qwe"/>
</bean>
</beans>
Run Code Online (Sandbox Code Playgroud)
最后需要注意的是,尽管你可以做到这一点,但你不应该这样做,除非它是必须的,因为这是一种不太自然的配置方式.如果您有多个类实例,最好坚持使用XML配置.
我只是要解决类似的案件.如果您可以重新定义课程,这可能会有效.
// This is not a @Component
public class Person {
}
@Component
public PersonOne extends Person {
public PersonOne() {
super("Joe", "Smith");
}
}
@Component
public PersonTwo extends Person {
public PersonTwo() {
super("Mary","Williams");
}
}
Run Code Online (Sandbox Code Playgroud)
然后,只要您需要自动装配特定实例,只需使用PersonOne或PersonTwo,其他地方只需使用Person.
归档时间: |
|
查看次数: |
57203 次 |
最近记录: |