1. 우선, Robot 타입의 bean을 정의한다.
@Component
public class Robot {
public void performTask() {
System.out.println("Performing a task.");
}
}
2. Robot 타입의 bean의 기능을 추가할 인터페이스들과 구현 클래스 하나씩을 정의한다.
public interface Flyable {
void fly();
}
public class FakeFlyable implements Flyable {
@Override
public void fly() {
System.out.println("Flying high in the sky!");
}
}
public interface Walkable {
void walk();
}
public class FakeWalkable implements Walkable {
@Override
public void walk() {
System.out.println("Walking on the ground.");
}
}
3. @org.aspectj.lang.annotation.DeclareParents 어노테이션으로, Robot 타입의 bean에 Flyable과 Walkable 인터페이스의 구현체를 합체(?)시키도록 정의한다. 이때, 각 인터페이스의 구현체는 defaultImpl 속성으로 기술한다.
@Aspect
@Component
public class RobotIntroductionAspect {
@DeclareParents(value = "com.example.Robot", defaultImpl = FakeFlyable.class)
public Flyable flyable;
@DeclareParents(value = "com.example.Robot", defaultImpl = FakeWalkable.class)
public Walkable walkable;
}
4. main 메서드를 실행하면, 마치 Robot이 FakeFlyable과 FakeWakable 클래스를 다중 상속한 것처럼 동작한다.
@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MainApp.class);
Robot robot = context.getBean(Robot.class);
robot.performTask(); // 기본 메서드 호출
((Flyable) robot).fly(); // fly 메서드가 호출됨!
((Walkable) robot).walk(); // walk 메서드가 호출됨!
}
}
하지만, 위 코드는 명시적 캐스팅이 항상 필요하다. AOP 기술도 필요하다. 그래서, 런타임에서의 성능저하는 필연적이다.
동일한 기능을 인터페이스의 디폴트 메서드를 활용한 방식으로 변경해 본 코드는 다음과 같다.
interface Flyable {
default void fly() {
System.out.println("Flying high in the sky!");
}
}
interface Walkable {
default void walk() {
System.out.println("Walking on the ground.");
}
}
class Robot implements Flyable, Walkable {
public void performTask() {
System.out.println("Performing a task.");
}
}
public class MainApp {
public static void main(String[] args) {
Robot robot = new Robot();
robot.performTask(); // 기존 메서드 호출
robot.fly(); // Flyable의 디폴트 메서드 호출
robot.walk(); // Walkable의 디폴트 메서드 호출
}
}
'DevLogs > LearningSpring' 카테고리의 다른 글
Spring의 *Aware 인터페이스들에 대한 정리 (2) | 2024.11.13 |
---|---|
MessageSource의 한글 깨짐 해결하기 (0) | 2024.11.13 |
@Value 어노테이션에 SpEL 사용법 (0) | 2024.10.31 |