반응형
01. AOP의 개요
절차지향
- 대형 프로그램만들 시 매우 많은 함수들을 사용하므로 점점 관리하기가 어려워져서,
- 함수를 통해 명령들을 모아 모듈화 하여 이용했음 (ex. C언어)
- 단점: 함수는 자료형이 아니므로 배포가 불가능함
객체지향(OOP)
- 함수(메소드)뿐만 아니라 필요한 변수(필드)까지 모두 모듈화하여 사용함
- 이를 클래스라 부름 : 클래스 자료형 = 필드 + 메소드 (ex. C++언어가 나옴)
- 또한 모듈화된 자료형으로 만들었기 때문에 배포 가능
- 원하는 기능들을 가져가다가 손쉽게 이용 가능
- 그러나 너무 강력한 모듈화..
- 프로그램 만들 시 공통된 코드들(ex. 보안코드)이 반복되어 나오는데, 자바는 파일들을 가져다 삽입하는 기술이 없음
- JSP에서 제공해준 include(JSP에서 만든 기술 중 하나) 액션 태그는 자바가 아님..!!!
- 객체지향프로그래밍은 모든 기능을 하나의 객체가 모두 다 가지고 있어야함
- 즉, 클래스마다 필요한 코드들이 같다면 중복해서 사용해야함
- 중복된 코드를 최소화할 수 있도록 다른 클래스를 만들어 관계를 맺어 가져다 씀
- 그러나 코드가 중복된다고 관계를 맺는 건 좋지 않음
- 관계란 상속관계 - is A 과 포함관계 - has A처럼 객체간의 관계가 있어야 하는데,
- 코드의 중복성을 회피하고자 다른 클래스를 만들어 억지로 관계를 맺어버린다면 코드가 지저분해지고, 생산성 떨어지고, 객체간의 결합도가 높으면 재활용성 떨어지고, 유지보수의 효율성이 떨어짐
- 이를 해결하고자 AOP(관점지향프로그래밍)가 나옴
관점지향(AOP)
- 관계를 맺지 않아도 프로그램이 실행될 때 AOP기능을 제공해주는 프로그램이 각각의 클래스에서 필요한 기능만 가져다가 합쳐서 프로그램에서 실행될 수 있도록 만들어줌
- 기능은 핵심관심코드와 횡단관심코드로나뉨
02. OOP vs AOP
1) OOP
🖤OopOne 클래스
- 억지로 관계 맺은 OopOne - OopLogger
package xyz.itwill06.oop;
//OOP 단점 : 모듈화가 너무 강력하여 핵심관심코드와 횡단관심코드를 분리하여 프로그램을 작성이 어려움
// => 코드의 중복성이 높아 프로그램에 생산성 및 유지보수의 효율성 감소
public class OopOne {
/*
//메소드가 사용할 명령들 중 중복명령은 [private]로 만들어 가져다 사용 - 유지보수의 효율성 증가
private void beforelog() {
System.out.println("*** 메소드의 명령(핵심관심코드)이 실행되기 전에 기록될 내용 ***"); //횡단관심코드
}
*/
//메소드가 사용할 중복명령을 클래스로 만들어 사용(모든 클래스가 사용) - 유지보수의 효율성 증가 & OOP의 개념 위반
//=> 그러나!!! 코드의 중복을 피하기 위해 관계도 없는 횡단관심과 핵심관심을
//억지로 관계를 맺어(포함관계 OopOne - logger) 사용하는 것은
//OOP의 추상화와 캡슐화의 개념을 위반함
private OopLogger logger=new OopLogger();
public void display1() {
//횡단관심코드 : 프로그램 실행에 보조적인 기능을 제공하는 명령 (어떠한 기능을 구현하기 위해 반드시 필요한 명령)
//=> 로그 처리(기록), 권한처리(인증), 트랜잭션처리(Commit&Rollback), 예외처리(try-catch)
//System.out.println("*** 메소드의 명령(핵심관심코드)이 실행되기 전에 기록될 내용 ***");
//beforelog();
logger.beforelog(); //횡단관심코드
//핵심관심코드 : 프로그램 실행에 핵심적인 기능을 제공하는 명령 (기능 구현과 별개의 명령)
// => 데이타 처리 명령
System.out.println("*** OopOne 클래스의 display1() 메소드 호출 ***"); //핵심관심코드
}
public void display2() {
//System.out.println("*** 메소드의 명령(핵심관심코드)이 실행되기 전에 기록될 내용 ***");
//beforelog();
logger.beforelog();
System.out.println("*** OopOne 클래스의 display2() 메소드 호출 ***");
}
public void display3() {
//System.out.println("*** 메소드의 명령(핵심관심코드)이 실행되기 전에 기록될 내용 ***");
//beforelog();
logger.beforelog();
System.out.println("*** OopOne 클래스의 display3() 메소드 호출 ***");
}
}
🖤OopTwo 클래스
- 억지로 관계 맺은 OopTwo - OopLogger
package xyz.itwill06.oop;
public class OopTwo {
/*
private void beforelog() {
System.out.println("*** 메소드의 명령(핵심관심코드)이 실행되기 전에 기록될 내용 ***");
}
*/
//억지로 포함관계를 맺음 (OopOne - logger) - 유지보수의 효율성 증가 & OOP의 개념 위반
private OopLogger logger=new OopLogger();
public void display1() {
//System.out.println("*** 메소드의 명령(핵심관심코드)이 실행되기 전에 기록될 내용 ***");
//beforelog();
logger.beforelog();//횡단관심코드
System.out.println("*** OopTwo 클래스의 display1() 메소드 호출 ***");//핵심관심코드
}
public void display2() {
//System.out.println("*** 메소드의 명령(핵심관심코드)이 실행되기 전에 기록될 내용 ***");
//beforelog();
logger.beforelog();
System.out.println("*** OopTwo 클래스의 display2() 메소드 호출 ***");
}
public void display3() {
//System.out.println("*** 메소드의 명령(핵심관심코드)이 실행되기 전에 기록될 내용 ***");
//beforelog();
logger.beforelog();
System.out.println("*** OopTwo 클래스의 display3() 메소드 호출 ***");
}
}
🖤OopLogger 클래스
- 억지로 관계 맺은 OopOne - OopLogger
- 억지로 관계 맺은 OopTwo - OopLogger
package xyz.itwill06.oop;
public class OopLogger {
public void beforelog() {
System.out.println("*** 메소드의 명령(핵심관심코드)이 실행되기 전에 기록될 내용 ***"); //횡단관심코드
}
}
🖤OopApp 실행프로그램
package xyz.itwill06.oop;
public class OopApp {
public static void main(String[] args) {
OopOne one = new OopOne();
OopTwo two = new OopTwo();
one.display1();
one.display2();
one.display3();
two.display1();
two.display2();
two.display3();
}
}
2) AOP
🖤핵심관심모듈 : (부모) Aop 인터페이스
package xyz.itwill06.oop;
public interface Aop {
void display1();
void display2();
void display3();
}
🖤핵심관심모듈 : (자식) AopOne 클래스
- 아무런 관계가 없는 AopOne - AopLogger
package xyz.itwill06.oop;
//핵심관심모듈 : 핵심관심코드만 이용하여 메소드를 작성한 클래스
public class AopOne implements Aop {
@Override
public void display1() {
System.out.println("*** AopOne 클래스의 display1() 메소드 호출 ***");
}
@Override
public void display2() {
System.out.println("*** AopOne 클래스의 display2() 메소드 호출 ***");
}
@Override
public void display3() {
System.out.println("*** AopOne 클래스의 display3() 메소드 호출 ***");
}
}
🖤핵심관심모듈 : (자식) AopTwo 클래스
- 아무런 관계가 없는 AopTwo - AopLogger
package xyz.itwill06.oop;
//핵심관심모듈
public class AopTwo implements Aop {
@Override
public void display1() {
System.out.println("*** AopTwo 클래스의 display1() 메소드 호출 ***");
}
@Override
public void display2() {
System.out.println("*** AopTwo 클래스의 display2() 메소드 호출 ***");
}
@Override
public void display3() {
System.out.println("*** AopTwo 클래스의 display3() 메소드 호출 ***");
}
}
🖤횡단관심모듈 : AopLogger 클래스 - Advice
- 아무런 관계가 없는 AopOne - AopLogger
- 아무런 관계가 없는 AopTwo - AopLogger
package xyz.itwill06.oop;
//횡단관심모듈 : 횡단관심코드만 이용하여 메소드를 작성한 클래스 - Advice 클래스
public class AopLogger {
public void beforeLog() {
System.out.println("*** 메소드의 명령(핵심관심코드)이 실행되기 전에 기록될 내용 ***");
}
}
🖤동작 : AopProxy 클래스 - Aspect - (Spring에서는.. AspectJ 라이브러리가 Proxy 역할 해줌 )
- 핵심관심모듈의 메소드에 횡단관심모듈의 메소드를 삽입하여 동작하는 기능을 제공하는 클래스 - Aspect (= 관점에 대한 결과물)
package xyz.itwill06.oop;
//Proxy 클래스 : 핵심관심모듈의 메소드에 횡단관심모듈의 메소드를 삽입하여 동작하는 기능을 제공
//하는 클래스 - Aspect
public class AopProxy implements Aop {
//핵심관심모듈로 선언된 클래스의 객체를 저장하기 위한 필드
// => 필드의 자료형을 인터페이스로 선언하여 모든 자식 클래스의 객체 저장 가능
private Aop target;
//횡단관심모듈로 선언된 클래스의 객체를 저장하기 위한 필드
private AopLogger logger;
//필드에 객체를 생성하여 저장하거나 매개변수로 객체를 전달받아 저장 - 의존성 주입(DI)
//=>AOP는 만들어서 저장하고 target은 전달받아 저장할 것임
public AopProxy(Aop target) {
super();
this.target = target;
logger=new AopLogger();
}
//인터페이스의 추상메소드(PointCut)를 오버라이드 선언하여 핵심관심코드와 횡단관심코드를
//결합(weaving)하여 실행되도록 작성 - Weaving
// => 핵심관심모듈의 메소드 호출 전 또는 후에 횡단관심모듈의 메소드가 호출하여
//실행되도록 설정 - 횡단관심 모듈의 메소드 삽입 위치 : JoinPoint
@Override
public void display1() {
logger.beforeLog(); //횡단관심코드를 삽입해서 실행해주세요
target.display1(); //핵심관심코드를 삽입해서 실행해주세요
}
@Override
public void display2() {
logger.beforeLog();
target.display1();
}
@Override
public void display3() {
logger.beforeLog();
target.display1();
}
}
🖤AopApp 실행프로그램
package xyz.itwill06.oop;
public class AopApp {
public static void main(String[] args) {
AopProxy one = new AopProxy(new AopOne()); //매개변수를 통해 핵심관심코드의 객체 전달받아 결합시킴
AopProxy two = new AopProxy(new AopTwo());
one.display1();
one.display2();
one.display3();
two.display1();
two.display2();
two.display3();
}
}
반응형
'framework > spring AOP(관점지향)' 카테고리의 다른 글
[springAOP] 6. 스키마기반의 AOP 만들어 사용하기 | ExecutionTimeApp프로그램 (0) | 2024.07.31 |
---|---|
[springAOP] 5. 스키마기반의 AOP 만들어 사용하기 | Advice클래스의 매개변수 (0) | 2024.07.31 |
[springAOP] 4. 스키마기반의 AOP 만들어 사용하기 | Advice클래스 (0) | 2024.07.30 |
[springAOP] 3. AOP 만들기 전 설정할 것 (0) | 2024.07.30 |
[springAOP] 2. AOP의 용어 | springAOP의 특징 및 생성법 (0) | 2024.07.30 |