MyPrototype、MyControllerspring
@Component @Scope("prototype") public class MyPrototype { } @Controller public class MyController { @Autowired MyPrototype myPrototype; public MyPrototype getMyPrototype() { return myPrototype; } }
MyConfigapp
@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是不同的,要怎麼辦呢?ide
重寫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框架耦合度過高。this
若是是XML配置的話,用lookup-method
標籤,好比:spa
<bean id="commandManager" class="com.learn.di.CommandManager"> <lookup-method name="createCommand" bean="myCommand"/> </bean>
MyController改寫以下:prototype
@Controller public abstract class MyController{ @Autowired MyPrototype myPrototype; public MyPrototype getMyPrototype() { return createMyPrototype(); } @Lookup() protected abstract MyPrototype createMyPrototype() ; }
測試代碼等其餘不變。
運行結果以下:
經過@Lookup註解,能夠看出,兩次的地址是不同的。code
di.xml配置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。