spring学习之方法注入
单例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。