单例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
标签,比如:
MyController改写如下:
@Controller
public abstract class MyController{
@Autowired
MyPrototype myPrototype;
public MyPrototype getMyPrototype() {
return createMyPrototype();
}
@Lookup()
protected abstract MyPrototype createMyPrototype() ;
}
测试代码等其他不变。
运行结果如下:
通过@Lookup注解,可以看出,两次的地址是不一样的。
方法替换
di.xml配置
String
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。