单例bean注入多例bean
MyPrototype、MyController
@Component
@Scope("prototype")
public class MyPrototype {
}
@Controller
public class MyController {
@Autowired
MyPrototype myPrototype;
public MyPrototype getMyPrototype() {
return myPrototype;
}
}
MyConfig
@Configuration
@ComponentScan(value="com.learn.annotation2")
public class MyConfig {
}
测试代码
@Test
public void test(){
ApplicationContext app = new AnnotationConfigApplicationContext(MyConfig.class);
MyController myController=app.getBean("myController",MyController.class);
System.out.println(myController.getMyPrototype());
System.out.println(myController.getMyPrototype());
}
运行结果如下:
可以看出,当单例myController中注入了多例的myPrototype,myPrototype对于myController还是一个实例,如果我们想每次获取的myPrototype是不一样的,要怎么办呢?
ApplicationContextAware
重写MyController,继承ApplicationContextAware接口设置ApplicationContext,并重写getMyPrototype方法通过applicationContext获取bean。
@Controller
public class MyController implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Autowired
MyPrototype myPrototype;
public MyPrototype getMyPrototype() {
return applicationContext.getBean("myPrototype",MyPrototype.class);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
测试代码不变
运行结果如下:
可以看出这两个地址不一样。但是这样的处理是不优雅的,业务代码和spring框架耦合度太高。
@Lookup
如果是XML配置的话,用lookup-method
标签,比如:
<bean id="commandManager" class="com.learn.di.CommandManager">
<lookup-method name="createCommand" bean="myCommand"/>
</bean>
MyController改写如下:
@Controller
public abstract class MyController{
@Autowired
MyPrototype myPrototype;
public MyPrototype getMyPrototype() {
return createMyPrototype();
}
@Lookup()
protected abstract MyPrototype createMyPrototype() ;
}
测试代码等其他不变。
运行结果如下:
通过@Lookup注解,可以看出,两次的地址是不一样的。
方法替换
di.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:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myValueCalculator" class="com.learn.di.MyValueCalculator">
<replaced-method name="computeValue" replacer="replacementComputeValue">
<arg-type>String</arg-type>
</replaced-method>
</bean>
<bean id="replacementComputeValue" class="com.learn.di.ReplacementComputeValue"/>
</beans>
MyValueCalculator和ReplacementComputeValue
public class MyValueCalculator {
public String computeValue(String input) {
System.out.println(input);
return "old method";
}
}
public class ReplacementComputeValue implements MethodReplacer {
@Override
public Object reimplement(Object o, Method method, Object[] objects) throws Throwable {
return "new method";
}
}
测试代码
@Test
public void test11() {
ApplicationContext app = new ClassPathXmlApplicationContext("di10.xml");
MyValueCalculator myValueCalculator = app.getBean("myValueCalculator", MyValueCalculator.class);
System.out.println(myValueCalculator.computeValue("input"));
}
运行结果如下:
在配置文件中,设置了myValueCalculator类中的computeValue方法,由replacementComputeValue的方法替换,最终调用的是replacementComputeValue的reimplement方法,输出new method。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。