[목차]

2. 생성자 주입(Constructor Injection)

① meta.xml

② 생성자 호출 
③ MVC 패턴 및 다형성 활용한 프로그래밍

④ 생성자 주입(construnctor injection)
⑤생성자 주입방법 2

3. setter 주입(setter injection) 
4. new를 이용한 객체생성과 Spring 객체 생성의 차이 

 


[내용]

2. 생성자 주입(Constructor Injection)

public static void main(String[] args) {
	// new로 객체 생성시 매번 생성된다.
	
	MessageImpl m1 = new MessageImpl("김이상");
	m1.sayHi();
	
	MessageImpl m2 = new MessageImpl("김이상");
	m2.sayHi();
	
	System.out.println("주소 : "+m1);
	System.out.println("주소 : "+m2);
}

 => new를 이용한 객체 생성

 

① meta.xml

<beans>
	<bean id="moneyCalc" name="aa,bb,cc" class="pack.model.MoneyCalc"/>	
	<bean id="myProcess" class="pack.controller.MyProcess">
		<constructor-arg>
			<ref bean="moneyCalc"/>
		</constructor-arg>
	</bean>
</beans>

 => 매개변수가 있는 생성자일 경우 <contructor-arg>와 <ref> 태그를 사용하여 매개변수를 입력한다.

 => 매개변수도 생성자를 생성한다.

<beans>
	<bean id="moneyCalc" name="aa,bb,cc" class="pack.model.MoneyCalc"/>	
	<bean id="myProcess" class="pack.controller.MyProcess">
		<constructor-arg>
			<ref bean="aa"/>
		</constructor-arg>
	</bean>
</beans>

 => id나 name 둘중 무엇을 사용해도 상관없으며, <ref bean="name">에서 name을 호출가능.

 

 

② 생성자 호출

public class Main {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("money_init.xml");
		MyInter inter = (MyInter)context.getBean("myProcess");
		inter.inputMoney();
		inter.showResult();
	}
}

 => ApplicationContext 객체 생성시 xml에 연결된 모든 생성자가 호출되며, 각 객체가 생성된다.

 => context의 getBean()메소드로 객체를 get하여 메소드를 사용한다.

 => getBean() 메소드의 리턴값은 Object로 다형성을 사용하여 캐스팅하여 객체를 대입한다.

 => getBean() 리턴 객체도 다형성을 사용하여 interface 객체에 대입하여 사용하는 것을 지향한다.

 

 

③ MVC 패턴 및 다형성 활용한 프로그래밍

 

pakage Controller(Servlet) Model(Dto, Dao-sql)
Interface BusinessInterface ModelInterface
 
Class BusinessClass ModelClass

 => 다형성을 갖춘 MVC Pattern 작성을 지향하여 프로그래밍한다.

 => Controller의 Business Class에서 Model Interface를 호출하여 사용한다.

 => 각 모델은 다형성을 활용하여 테이블에 따른 Sql문을 호출하여 DB와 연결된다.

 => [src.main/java]에 작성한다.

 

- Business Interface

public interface MyInter {
	void inputMoney();
	void showResult();
}

 - Business Class

public class MyProcess implements MyInter{
	private MoneyInter inter;
	private int result[];
	
	public MyProcess(MoneyInter inter) {
		this.inter = inter;
	}
	
	public void inputMoney() {
		//키보드로 금액입력
		try {
			InputStreamReader reader = new InputStreamReader(System.in);
			BufferedReader br = new BufferedReader(reader);
			int myMoney=0;
			System.out.println("금액입력");
			String data = br.readLine();
			myMoney = Integer.parseInt(data);
			result = inter.calcMoney(myMoney);
		} catch (Exception e) {
			System.out.println("inputMoney err "+e);
		}
	}

	public void showResult() {
		//계산이 끝난 배열 자료 출력.
		System.out.println("만원 : "+result[0]+"개");
		System.out.println("천원 : "+result[1]+"개");
		System.out.println("백원 : "+result[2]+"개");
		System.out.println("십원 : "+result[3]+"개");
		System.out.println("일원 : "+result[4]+"개");
	}

}

 => 생성자에 모델의 interface 객체를 매개변수로 받아 사용.

 

- Model Interface

public interface MoneyInter {
	int[] calcMoney(int money);
}

 

- Model Class

public class MoneyCalc implements MoneyInter{
	public MoneyCalc() {
	}
	public int[] calcMoney(int money) {
		//단위별 금액 건수 계산용
		int result[] = new int[5];
		int temp=0;
		int len = result.length;
		for(int i=0; i<len;i++) {
			if(i == 0) {
				result[i] = money/(int)Math.pow(10, (len-1-i));
				temp=money%(int)Math.pow(10, (len-1-i));
				continue;
			}
			result[i] = temp/(int)Math.pow(10, (len-1-i));
			temp=temp%(int)Math.pow(10, (len-1-i));
		}
		return result;
	}
}

 

③ 생성자 주입(construnctor injection)

 

 - ShowData(Dao)

public class ShowData {
	public String toAlias() {
		return "홍길동";
	}
	
	public String toHobby() {
		return "운동";
	}
}

 - MyProcess(Controller)

public class MyProcess { // 포함으로 약결합 진행
	private int age;
	private String name;
	private ShowData showData; // Class Type
	
	public MyProcess(int age, String name, ShowData showData) {
		this.age = age;
		this.name = name;
		this.showData = showData;
	}
	
	public void printData() {
		System.out.println(name+age+showData.toAlias()+showData.toHobby());
	}
}

 - xml

<beans>
	<bean id="showData" class="pack.model.ShowData"/>	
	<bean id="myProcess" class="pack.controller.MyProcess">
		<constructor-arg>
			<value>13</value>
		</constructor-arg>
		<constructor-arg>
			<value>홍길동</value>
		</constructor-arg>
		<constructor-arg>
			<ref bean="showData"/>
		</constructor-arg>
	</bean>
</beans>

- main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("init.xml");
	MyProcess myProcess = (MyProcess)context.getBean("myProcess");
	myProcess.printData();
}

④ 생성자 주입방법 2

 - MessageInter

public interface MessageInter {
	void sayHi();
}

 - MessageImpl

public class MessageImpl implements MessageInter{
	private String name1;
	private String name2;
	private int year;
	private MyClass myclass;
	private String spec;
	
	// 생성자 주입
	public MessageImpl(String name1, String name2, int year, MyClass myclass) {
		this.name1=name1;
		this.name2=name2;
		this.year=year;
		this.myclass = myclass;
	}
	
	//setter 주입
	public void setSpec(String spec) {
		this.spec = spec;
	}
	
	// 출력담당 메소드
	public void sayHi() {
		String msg="이름 : "+name1+" / "+name2+"\n";
		msg+="직업 : "+(year+21)+"년 " + myclass.myData();
		msg+="\n보유기술 : "+spec;
		System.out.println(msg);
	}
}

 - arrange.xml

 ① 생성자 주입방법 1

<bean id="mbean" class="pack.MessageImpl" scope="singleton"> 
	<constructor-arg value="홍길동">
		<ref bean="name1"/>
	</constructor-arg>
</bean>
<bean id="mbean" class="pack.MessageImpl" scope="singleton"> 
// <bean> scope의 default는 singleton.
// scope를  prototype 설정 시 getBean()호출시 매번 객체를 생성한다.
// request, session은 web에서 사용.

	<constructor-arg index="1">
		<value>홍길동</value>
	</constructor-arg>
	
	<constructor-arg index="0">
		<value>도둑놈</value>
	</constructor-arg>
	
	<constructor-arg index="2" value="2000"/> // String -> int로 자동 변경된다.
	<constructor-arg index="2" type="int" value="2000"/> // 매개변수가 int일 경우 
	<constructor-arg index="2" type="int" value="이천"/> // error
	<constructor-arg index="3" type="pack2.MyClass" ref="myClass"/>
</bean>
<bean id="myClass" class="pack2.MyClass">
	<property name="data" value="자바"/> // setter injection
</bean>

② 생성자 주입방법 2

 : arrange.xml의 Namespace Tab에서 c, p check

<bean id="mbean" class="pack.MessageImpl"
			c:name1="고길동"
			c:name2="깡패"
			c:year="2000"
			c:myclass-ref="myClass"
			p:spec="sqld">
</bean>

<bean id="myClass" class="pack2.MyClass">
	<property name="data" value="자바"/><!-- setter injection -->
</bean>

 => contruct, setter injection 혼용가능

 

- main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("arrange.xml");
	ApplicationContext context = new ClassPathXmlApplicationContext("classpath:pack/arrange.xml");
	// src/main/java/pack에 있을경우 
	
	//다형성
	MessageInter inter = (MessageInter)context.getBean("mbean"); // 캐스팅을 interface로 한다.
	// MessageInter inter = (MessageImpl)context.getBean("mbean"); // 지양
	inter.sayHi();
	System.out.println("주소 : "+inter);
}

 


3. setter 주입(setter injection)

 

 - MyProcess

public class MyProcess {
	private int age;
	private String name;
	private ShowData showData;

	// setter를 이용해서 private 멤버에 값을 입력
	public void setAge(int age) {
		this.age = age;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setShowData(ShowData showData) {
		this.showData = showData;
	}
	
	public void printData() {
		System.out.println(name+age+showData.toAlias()+showData.toHobby());
	}
}

 - init.xml

① 방법 1

<bean id="myProcess" class="pack.MyProcess">
	<property name="age" value="22"/> //MyProcess의 setAge()를 호출한다. 
	<property name="name" value="김이상"/> // setName() 호출
	<property name="showData" ref="showData"/> //객체의 setter 호출시 ref를 사용한다.  
</bean>
 
<bean id="showData" class="pack.ShowData"/> // 다른 <bean>태그에서도 호출 가능

② 방법 2 : 하위 element로 사용

<bean id="myProcess" class="pack.MyProcess">
	<property name="age">
		<value>23</value>
	</property>
	<property name="name">
		<value>김이상</value>
	</property>
	<property name="showData">
		<bean class="pack.ShowData"/> // 해당 <bean>태그에서만 사용가능
	</property>
</bean>

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("init.xml");
	MyProcess myProcess = (MyProcess)context.getBean("myProcess");
	myProcess.printData();
}

 


 

4. new를 이용한 객체생성과 Spring 객체 생성의 차이

 

 - new

public static void main(String[] args) {
	// new로 객체 생성시 매번 생성된다.
	MessageImpl m1 = new MessageImpl("김이상");
	m1.sayHi();

	MessageImpl m2 = new MessageImpl("김이상");
	m2.sayHi();

	System.out.println("주소 : "+m1); // 주소 : pack.MessageImpl@74e28667
	System.out.println("주소 : "+m2); // 주소 : pack.MessageImpl@1cf6d1be
}

 - xml

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("arrange.xml");
	
	// getBean사용시 singletone으로 객체 생성
	MessageImpl impl1 = (MessageImpl)context.getBean("mbean");
	impl1.sayHi();
	
	MessageImpl impl2 = (MessageImpl)context.getBean("mbean");
	impl2.sayHi();
	
	System.out.println("주소 : "+impl1);
	System.out.println("주소 : "+impl2);
}

 

. 어노테이션 : 객체생성시 xml에 의존적 -> @annotation으로 대체.

① @Require 어노테이션 : setter를 사용하도록 제약을 건다.

 - Abc

 public class Abc {
	private int number;
	
	@Required // setter를 사용하도록 제약을 건다.
	public void setNumber(int number) {
		this.number = number;
	}
	
	public void printData() {
		System.out.println("number : "+number);
	}
}

 - anno1.xml

<beans>
	<context:annotation-config/>
	<bean id="abc" class="anno1.Abc">
		<property name="number" value="100"></property>
	</bean>
</beans>

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("anno1.xml");
	Abc abc = (Abc)context.getBean("abc");
	abc.printData();
}

② @Component : 객체 생성 

 - SenderInter

public interface SenderInter{
	void show();
}

 - Sender

@Component // 객체 생성 
public class Sender implements SenderInter{
	public void show() {
		System.out.println("show메소드 수행");
	}
}

- Sender2

//@Component = @Component("Sender2")// 객체 생성
@Component("별명")
public class Sender2 implements SenderInter{
	public void show() {
		System.out.println("Sender2의 show메소드 수행");
	}
}

③ @Service : @Component와 동일하나 Business 로직에서 사용한다.

④ @Autowired : setter가 내부적으로 정의되며, type에 의한 mapping 진행.

⑤ @Qualifier("아이디") : type에 대하여 mapping시 동일한 타입(같은 부모를 상속받는 자식) 객체가 복수인 경우 

     Qualifier의 아이디에 명시한 아이디로 mapping한다.

 - SenderProcess

//@Component
//@Service
@Service("SenderProcess") //Component와 동일
public class SenderProcess { // 서비스를 하는 비지니스 로직
	private String name = "tom";
    
	@Autowired  // xml의 type에 대한 mapping.
	//@Qualifier("sender2") // 동일한 타입의 객체(상속받는 자식 객체)가 복수인 경우 id로 mapping
	@Qualifier("별명")
	private SenderInter senderInter;
	
	//public void setSender(Sender sender) { // @Autowired사용시 삭제가능
	//	this.sender = sender;
	//}
    
	public void displayData() {
		System.out.println("displayData의 name : " + name);
		senderInter.show();
	}
}

 - xml

<context:annotation-config/> // @어노테이션을 사용가능하게 한다.
<bean id="senderProcess" class="anno2.SenderProcess"/>
<bean id="sender" class="anno2.Sender"/>
<bean id="sender2" class="anno2.Sender2"/>
 // SenderInter를 상속하는 class가 복수가 되면 type으로 mapping하기 때문에 식별자가 필요하다.
<bean class="anno2.Sender"/>
// type에 대한 mapping으로 id가 없어도 mapping된다.
<context:annotation-config/> // 생략 가능
<context:component-scan base-package="anno2"/> // pakage의 @Component, @Service가 작성된 class의 Bean을 생성.

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("anno2.xml");
	SenderProcess senderProcess = (SenderProcess)context.getBean("senderProcess");
	senderProcess.displayData();
}

 

+ Recent posts

1