introduction에 해당하는 글 1

[Spring] 인트로덕션(introduction), @DeclareParents

카테고리 없음|2019. 4. 29. 18:30

책을 보다 잘 모르던 기능이 보여서 정리 차원에서 글을 남긴다.

 

"인트로덕션"

어노테이션은 @DeclareParents 를 사용하며

다중 상속을 사용할 수  없는 상황에서 다중 상속처럼 여러 구현체를 사용할 수 있도록 해주는 기능

(사실 타겟 클래스에 설정된 인터페이스를 모두 implements 하게 하고 구현할 내용에 인터페이스 구현체들을 콜하는 방식으로 동적으로 구현해주는 기능, CGLib을 통해)

 

역시나 돌려보는게 이해하기 빠르다

 

예제 네이밍은 조금 이상하긴 하지만.. 설명을 붙이자면

Coffee 인터페이스와 Color 인터페이스가 존재하고

Coffee의 구현체인 Robusta와 Color의 구현체인 Black을 

인트로덕션을 사용해서 CoffeeColor 클래스가 Robusta와 Black을 상속 받은 것처럼 사용해보았다.

 

돌려보기 위해 준비할 클래스

 

0. config 클래스()

//@EnableAspectJAutoProxy 안해주면 에러난다..

package com.meteor.bbbb;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class ConfigTest {

}

1. introduction 될 클래스(TargetClass, ColorCoffee)

package com.meteor.bbbb;

import org.springframework.stereotype.Component;

@Component
public class ColorCoffee {

}

2. introduction 할 내용을 선언한 클래스(CoffeeIntroduction)

package com.meteor.bbbb;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class CoffeeIntroduction {

	@DeclareParents(value="com.meteor.bbbb.ColorCoffee", defaultImpl=Black.class)
	public Color col;

	@DeclareParents(value="com.meteor.bbbb.ColorCoffee", defaultImpl=Robusta.class)
	public Coffee coffee;
	
	
}

 

3. introduction에 사용되는 인터페이스(Coffee, Color)

package com.meteor.bbbb;

public interface Coffee {
	public void drink();
}

 

package com.meteor.bbbb;

public interface Color {
	public String getColor();

}

4. introduction에 사용되는 인터페이스 구현체 클래스(Robusta, Black)

 

package com.meteor.bbbb;

public class Robusta implements Coffee{
	@Override
	public void drink() {
		System.out.println("robusta drink");
	}

}
package com.meteor.bbbb;

public class Black implements Color{

	@Override
	public String getColor() {
		return "Black";
	}

}

 

마지막으로 돌려보는 테스트 코드

	@Test
	public void contextText2() {
		ApplicationContext context = new AnnotationConfigApplicationContext("com.meteor.bbbb");
		Coffee coffee  = (Coffee) context.getBean(ColorCoffee.class);
		coffee.drink();
		if(coffee instanceof Color) {
			Color col = (Color) coffee;
			System.out.println(col.getColor());
		}
	}

결과는 정상적으로 출력됬다

 

 

 

 

 

 

 

 

디버깅으로 빈 객체를 찍어보니 역시나 CGLIB 으로 프록시 객체를 만든것을 확인할 수 있었다

 

 

 

 

 

 

 

 

 

 

 

그런데.. 이렇게 쓰면 코드 가독성이 떨어질것 같은데..

package com.meteor.bbbb;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ColorCoffeeFix implements Coffee, Color{

	@Autowired
	private Coffee coffee;
	
	@Autowired
	private Color color;
	
	@Override
	public String getColor() {
		return color.getColor();
	}

	@Override
	public void drink() {
		coffee.drink();
	}

}

이렇게 쓰는게 더 좋지 않을까 싶다..

적절한 인트로덕션(introduction) 사용처를 찾아봐야..

댓글()