[Spring]Method Injection

Spring-framwork 提供了一種基於方法級的注入方式

考慮一種情況,一個singleton A 和一個 prototype B,A中有一個方法每次執行的時候都需要一個B的實例,由於Spring容器在初始A的時候已經初始好一切,那麼這個時候如何做到每次執行該方法的時候,提供一個依賴B呢?


解決有兩種方法:

1.通過實現 ApplicationContextAware 接口,硬編碼實現每次調用該方法的時候注入一個實例B,然而這種方法會使代碼和注入過程耦合在一起

2.提供一個abstract方法,Spring使用CGLIB重寫抽象方法提供注入 (Method Injection)

方法注入,提供了方法級的注入方式,保證每次執行到該方法的時候都會提供一個新的B實例來使用,由Spring容器通過配置完成解耦工作。


Command接口:

package com.interfaces;

public interface Command {
	void setState(String commandState);
	String execute();
}

Command實現:

package com.domain;

import com.interfaces.Command;

public class AttackCommand implements Command {
	private String commandState;
	private static int count = 0;
	private final int id = count++;
	public AttackCommand() {
		System.out.println("command init");
	}

	public String execute() {
		return "Attack Command " + id + ": starting attack " + commandState;
	}


	public void setState(String commandState) {
		this.commandState = commandState;
	}
}


Method 1:

package com.domain;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.interfaces.Command;

public class CoupleCommandManager implements ApplicationContextAware {
	private ApplicationContext applicationContext;

	public String process(String commandState) {
		Command command = createCommand();
		command.setState(commandState);
		return command.execute();
	}

	protected Command createCommand() {
		return applicationContext.getBean("attackCommand", Command.class);
	}

	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

}



Method 2:

package com.domain;

import com.interfaces.Command;

public abstract class CommandManager {
	public String process(String commandState){
		Command command = createCommand();
		command.setState(commandState);
		return command.execute();
	}
	
	protected abstract Command createCommand();
	
}

xml配置文件

	<bean id="attackCommand" class="com.domain.AttackCommand" scope="prototype"/>
	
	<bean id="coupleCommandManager" class="com.domain.CoupleCommandManager"></bean>
	<bean id="commandManager" class="com.domain.CommandManager">
		<lookup-method name="createCommand" bean="attackCommand"/>
	</bean>


java cfg:

 @Bean
	@Scope("prototype")
	public Command attackCommand() {
		return new AttackCommand();
	}

	@Bean
	public CommandManager commandManager() {
		return new CommandManager() {

			@Override
			protected Command createCommand() {
				return attackCommand();
			}
		};
	}




發佈了58 篇原創文章 · 獲贊 11 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章