spring學習之方法注入

單例bean注入多例bean

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());
}

運行結果以下:
image.png
能夠看出,當單例myController中注入了多例的myPrototype,myPrototype對於myController仍是一個實例,若是咱們想每次獲取的myPrototype是不同的,要怎麼辦呢?ide

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;
    }
}

測試代碼不變
運行結果以下:
image.png
能夠看出這兩個地址不同。可是這樣的處理是不優雅的,業務代碼和spring框架耦合度過高。this

@Lookup

若是是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() ;
}

測試代碼等其餘不變。
運行結果以下:
image.png
經過@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"));
}

運行結果以下:
image.png在配置文件中,設置了myValueCalculator類中的computeValue方法,由replacementComputeValue的方法替換,最終調用的是replacementComputeValue的reimplement方法,輸出new method。

相關文章
相關標籤/搜索