[목차]

5. AOP (Aspect Oriented Program)

* 스프링 AOP에서 용어
① AOP 구현

 


 

[내용]

5. AOP (Aspect Oriented Program)

 

: 핵심 로직에서 임의의 동작을 진행할 경우 사용. 
: 별도의 클래스로 정의하여 메소드를 탈부착식으로 사용한다.

: ex) 시큐리티, 로그인, 트랜잭션

 

 1) 설정

 ⓛ 사이트 접속 - search.maven.org/

 ② search창에 aspectjweaver 검색

 ③ version 선택

 ④ Apache Maven 내용 copy & paste

 ⑤ search창에 cglib 검색

 ⑥ version 선택

 ⑦ Apache Maven 내용 copy & paste

 ⑧ pom.xml에 Code 추가

<!-- aop -->
<dependencies>
	<dependency>
		<groupId>aspectj</groupId>
		<artifactId>aspectjweaver</artifactId>
		<version>1.5.4</version>
	</dependency>
	<dependency>
		<groupId>cglib</groupId>
		<artifactId>cglib</artifactId>
		<version>3.3.0</version>
	</dependency>
</dependencies>

 ⑨ 경로에 생성됨. C:\Users\wonh\.m2\repository\

 

2) code

- HelloInter

public interface HelloInter {
	void hello();
	void hi();	
}

 - HelloInterImpl

public class HelloInterImpl implements HelloInter{
	
	public HelloInterImpl() {
		System.out.println("HelloInterImpl 생성자");
	}
	
	public void hello() {
		System.out.println("hello 처리");
	}

	public void hi() {
		System.out.println("hi 처리");
	}
}

 - WriteInter

public interface WriteInter {
	void write();
}

 - WriteInterImpl

public class WriteInterImpl implements WriteInter{ // 핵심 로직을 가진 클래스
	
	public WriteInterImpl() {
		System.out.println("WriteInterImpl 생성자");
	}

	public void write() {
		System.out.println("write 수행");
	}
}

 - MyAspect

public class MyAspect { // 관심사항을 가진 클래스
	public void myLogOn() {
		System.out.println("핵심 메소드 수행전 로그온 작업");
	}
	
	public void myLogOut() {
		System.out.println("핵심 메소드 수행후 로그아웃 작업");
	}
	
	public void mySecurity() {
		System.out.println("핵심 메소드 수행전 보안설정");
	}
}

 - AspectProcess

public class AspectProcess { // 여러개의 관심사항들을 모아 처리하는 클래스
	private MyAspect myAspect; // 관심사항 클래스. 여러개 가능
	
	public void setMyAspect(MyAspect myAspect) {
		this.myAspect = myAspect;
	}
	
	public Object logging(ProceedingJoinPoint joinPoint) throws Throwable{
		Object object = null;
		
		myAspect.myLogOn();
		object = joinPoint.proceed(); // 메타파일에서 설정한 핵심 메소드 수행.
		myAspect.myLogOut();
		
		return object;
	}
	
	public Object logging2(ProceedingJoinPoint joinPoint) throws Throwable{
		Object object = null;
		
		myAspect.mySecurity();
		object = joinPoint.proceed(); // 메타파일에서 설정한 핵심 메소드 수행.
		return object;
	}
}

 => logging() 메소드는 myLogOn() -> 핵심로직 -> myLogOut() 순 호출

 => logging2() 메소드는 mySecurity() -> 핵심로직 순 호출

 - main

public static void main(String[] args) {
	//String[] configs = new String[] {"aop1core.xml"}; // 핵심만 수행
	String[] configs = new String[] {"aop1core.xml", "aop1.xml"}; // 핵심 + Aop 수행.
	
	ApplicationContext context = new ClassPathXmlApplicationContext(configs);
	
	WriteInter writeInter = (WriteInter)context.getBean("writeInterImpl");
	writeInter.write();
	System.out.println();
	
	HelloInterImpl helloInter = (HelloInterImpl)context.getBean("helloInterImpl"); // 방법 1
	HelloInter helloInter = context.getBean("helloInterImpl", HelloInter.class); // 방법 2
	helloInter.hi();
	helloInter.hello();
}

 - aop1core.xml

<bean id="writeInterImpl" class="aop1.WriteInterImpl"/>
<bean id="helloInterImpl" class="aop1.HelloInterImpl"/>

 - aop1.xml

<!-- Aspect(Advice) -->
<bean id="aspectProcess" class="aop1.AspectProcess">
	<property name="myAspect" ref="myAspect"/>
</bean>
<bean id="myAspect" class="aop1.MyAspect"/>

<!-- Aop 설정 -->
<aop:config>
	<aop:pointcut expression="execution(public void wri*(..))" id="poi1"/>
	// wri로 시작하고 매개변수가 0개 이상인 메소드
	// <aop:pointcut expression="execution(public void write())" id="poi1"/>
	<aop:aspect ref="aspectProcess">
		<aop:around method="logging" pointcut-ref="poi1"/>
	</aop:aspect>
</aop:config>
<aop:config>
	<aop:pointcut expression="execution(public void hel*(..)) or execution(public void hi*(..))" id="poi2"/>
	// or || and &&
	<aop:aspect ref="aspectProcess">
		<aop:around method="logging2" pointcut-ref="poi2"/>
	</aop:aspect>
</aop:config>

 => 핵심 로직의 wri로 시작하고 메개변수가 0개 이상인 메소드가 호출될때 AspectProcess(Aspect를 처리하는) 클래스의 logging() 메소드가 실행된다.

 => 핵심 로직의 hel로 시작하고 메개변수가 0개 이상인 메소드 또는 hi로 시작하는 메소드가 호출될때 AspectProcess클래스의 logging2() 메소드가 실행된다.

 


 - ArticleInter

public interface ArticleInter {
	void select();
}

 

- ArticleDao

//@Component
//@Repository
@Repository("articleDao")

public class ArticleDao implements ArticleInter{

	public void select() {
		System.out.println("db의 상품 자료를 read");
	}
}

 - LogicInter

public interface LogicInter {
	void selectData_process();
}

 - LogicImpl

public class LogicImpl implements LogicInter{
	private ArticleInter articleInter; 
    
	public LogicImpl() {
	}
	
	public LogicImpl(ArticleInter articleInter) {
		this.articleInter = articleInter; 
	}
	
	public void selectData_process() {
		System.out.println("selectData_proces 수행");
		articleInter.select();
	}
}
@Service
public class LogicImpl implements LogicInter{

	@Autowired
	//@Qualifier("aticleDao")
	private ArticleInter articleInter; 
	
	public void selectData_process() {
		System.out.println("selectData_proces 수행");
		articleInter.select();
	}
}

 

 - ProfileAdvice

public class ProfileAdvice { // Advice, Aspect
	public Object abc(ProceedingJoinPoint joinPoint) throws Throwable{
		//핵심 메소드 이름 얻기
		String methodName = joinPoint.getSignature().toString();
		
		System.out.println(methodName+" 시작 전 작업");
		Object object = joinPoint.proceed(); // 핵심 메소드
		System.out.println(methodName+" 처리 후 작업");
		
		return object;
	}
}
@Aspect
@Component
public class ProfileAdvice { // Advice, Aspect
	@Around("execution(public void selectData_process())")
	public Object abc(ProceedingJoinPoint joinPoint) throws Throwable{
		//핵심 메소드 이름 얻기
		String methodName = joinPoint.getSignature().toString();
		
		System.out.println(methodName+" 시작 전 작업");
		Object object = joinPoint.proceed(); // 핵심 메소드
		System.out.println(methodName+" 처리 후 작업");
		
		return object;
	}
}

 

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("aop2.xml");
	LogicInter inter = (LogicInter)context.getBean("logicImpl");
	inter.selectData_process();
}

 - aop2.xml

<!-- 핵심 로직 처리용 클래스 -->
<bean id="logicImpl" class="aop2.LogicImpl">
	<constructor-arg>
		<ref bean="articleDao"/>
	</constructor-arg>
</bean>
<bean id="articleDao" class="aop2.ArticleDao"></bean>

<!-- Aop 설정 -->
<bean id="profileAdvice" class="aop2.ProfileAdvice"/>
<aop:config>
	<aop:aspect ref="profileAdvice">
		<aop:pointcut expression="execution(public void selectData_process())" id="poi"/>
		<aop:around method="abc" pointcut-ref="poi"/>
	</aop:aspect>
</aop:config>	

 => 핵심로직의 selectData_process()메소드 호출 시 profileAdvice클래스의 abc()메소드가 호출.

<!-- 객체 생성 : 어노테이션 -->
<context:component-scan base-package="aop3"/>
<!-- Aop 설정 -->
<aop:aspectj-autoproxy/>

 

 

 

* 스프링 AOP에서 용어


 - Joinpoint : ‘클래스의 인스턴스 생성 시점’, ‘메소드 호출 시점’ 및 ‘예외 발생 시점’ 과 같이 어플리케이션을 실행할 때 특정 작업이 시작되는 시점을 의미.

 - Advice : 조인포인트에 삽입되어 동작할 수 있는 코드를 말함.

 - Pointcut : 여러 개의 조인포인트를 하나로 결합한(묶은) 것을 말함.

 - Advisor : 어드바이스와 포인트컷을 하나로 묶어 취급한 것을 말함.

 - Weaving : 어드바이스를 핵심 로직 코드에 삽입하는 것을 말함.

 - Target : 핵심 로직을 구현하는 클레스.

 - Aspect : 여러 객체에 공통으로 적용되는 공통 관점 사항을 말함.

 

 

1) AOP 구현

 - LogicInter

public interface LogicInter {
	void startProcess();
}

 

 - LogicImpl

@Service // @Component와 동일하지만 가독성을 위해 Service기능을 사용하면 @Service를 사용.
public class LogicImpl implements LogicInter{
	
	public LogicImpl() {
	}
	
	public void startProcess() {
		System.out.println("핵심 로직 수행");
	}
}

 

 - aop4.xml

<!-- 어노테이션을 사용하여 객체 생성 -->
<context:component-scan base-package="aop4"/>
<!-- aop를 사용하도록 설정 -->
<aop:aspectj-autoproxy/>

    <context:component-scan base-package="패키지명"/>
    <aop:aspectj-autoproxy/>

 

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("aop4.xml");
	LogicInter inter = (LogicInter)context.getBean("logicImpl");
	// getBean의 매개변수 : @객체 생성할 클래스명을 첫글자 소문자로 변경하여 생성. 
	inter.startProcess();
}

 

 - RunAspect

// 아이디가 같으면 핵심로직 수행, 다르면 수행하지않도록 구현.
@Component
@Aspect // 독립적으로 동작할 관심 로직 클래스에 사용
public class RunAspect {
	
	@Around("execution(public void startProcess())")
	// 핵심로직의 메소드를 선택. 해당메소드 호출시 관심 메소드 호출.
	//@Around는 핵심로직 실행 전/후 모두 기능을 추가할 수 있다.
	public Object trace(ProceedingJoinPoint joinPoint) throws Throwable{
		
		System.out.println("AOP 시작 : 핵심 로직 처리전 id 검증");
		System.out.print("input id : ");
		Scanner scanner = new Scanner(System.in);
		String id = scanner.nextLine();
		if(! id.equalsIgnoreCase("aa")) { //equalsIgnoreCase() 대소문자 구분하지않고 비교.
			System.out.println("id 불일치하여 작업을 종료합니다.");
			return null;
		}
		
		Object obj = joinPoint.proceed(); // 핵심 로직 수행.
		
		return obj;
	}
}

    @Component

    @Aspect

    @Around("excution(핵심 로직의 메소드)")

    public Object 관심메소드명(ProceedingJoinPoint joinPoint) throws Throwable{ .. }

    Object obj = joinPoint.proceed();

    str1.equalsIgnoreCase(str2)

 

 

 

 

[목차]

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