신규 블로그를 만들었습니다!
AOP
Aspect Oriented Programing
관점 지향 프로그래밍
프로그래밍을 하다보면, 공통적인 기능이 많이 발생한다.
이러한 공통기능을 모든 모듈에 적용하기 위한 방법으로 상속을 이용한다.
상속도 좋은 방법이지만, JAVA에서는 다중 상속이 불가능하다.
이러한 모듈을 상속받아 공통 기능을 부여하기에는 한계가 있다.
그리고, 기능 구현부분에서
핵심코드와 공통기능코드가 섞여있어서
보기에도 불편하고, 효율성이 떨어진다.
이러한 이유로 AOP가 등장했다.
AOP방법은 핵심 기능과 공통 기능을 분리 시켜놓고,
공통 기능을 필요로 하는 핵심 기능들에서 사용하는 방식이다.
(핵심기능은 변화하지만, 공통기능은 다시 적용이 가능하다.)
즉, AOP는 핵심기능과 공통기능을 분리시킨다는 부분을 주의깊게 보자
주요용어
Aspect : 공통기능
Advice : Aspect의 기능 자체
Jointpoint : Advice를 적용해야 되는 부분(ex : 필드, 메소드 / 스프링에서는 메소드만 해당)
Pointcut : Jointpoint의 부분으로 실제로 Advice가 적용된 부분
Weaving : Advice를 핵심기능에 적용하는 행위
스프링에서 AOP 구현방법 : proxy를 이용한다.
client(호출부) -> proxy -> Target(핵심기능)
- step1. client가 프록시한테 요청해서 공통기능을 실행
- stpe2. 프록시가 다시 Target으로 가서 핵심기능을 실행
- step3. 다시 공통기능을 실행하기 위해, 프록시로 와서 공통기능 실행
(프록시가 중간에서 '대행' 역할을 한다.)
스프링에서 AOP 구현방식
-
방법1. XML 스키마 기반의 AOP구현
-
방법2. @Aspect 어노테이션 기반의 AOP 구현
방법 1. XML기반의 AOP구현
<설정할 부분>
-
의존설정(pom.xml)
<!-- AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency>
-
공통기능의 클래스 제작 - Advice 역할 클래스
// proxy
public class LogAop {
// 경과시간 체크하는 공통기능 메소드
public Object loggerAop(ProceedingJoinPoint joinPoint) throws Throwable {
//
}
}
-
XML설정 파일에 Aspect 설정
<bean id="logAop" class="com.edu.ex.LogAop"></bean>
<aop:config>
<aop:aspect id="logger" ref="logAop">
<aop:pointcut expression="within(com.edu.ex.*)" id="publicMethod"/>
<aop:around pointcut-ref="publicMethod" method="loggerAop"/>
</aop:aspect>
</aop:config>
코드를 통해 알아보기
Main.java
package com.edu.ex;
import org.springframework.context.support.GenericXmlApplicationContext;
public class Main {
public static void main(String[] args) throws Exception {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationCTX.xml");
Student student = ctx.getBean("student", Student.class);
student.getInfo();
Worker worker = ctx.getBean("worker", Worker.class);
worker.getInfo();
ctx.close();
}
}
단순한 Main함수
Student.java
package com.edu.ex;
public class Student {
private String name;
private int age;
// get set method
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// constructor
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
public void getInfo() {
System.out.println(">> name : " + name);
System.out.println(">> age : " + age);
}
}
단순한 VO,
정보를 확인할 getInfo() 출력함수를 만들었다.
Worker.java
package com.edu.ex;
public class Worker {
private String name;
private int age;
private String job;
// constructor
public Worker(String name, int age, String job) {
this.name = name;
this.age = age;
this.job = job;
}
public Worker() {
}
// get set method
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public void getInfo() {
System.out.println(">> name : " + name);
System.out.println(">> age : " + age);
System.out.println(">> job : " + job);
}
}
단순한 VO,
정보를 확인할 getInfo() 출력함수를 만들었다.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId>
<artifactId>exam02</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<!--
생략
-->
</properties>
<dependencies>
<!--
생략
-->
<!-- AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency>
</dependencies>
</project>
마지막에 'aspectj' dependency를 추가 한다.
메이븐 디펜던시에 라이브러리가 추가된것을 확인할 수 있다.
applicationCTX.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<bean id="logAop" class="com.edu.ex.LogAop"></bean>
<aop:config>
<aop:aspect id="logger" ref="logAop">
<aop:pointcut expression="within(com.edu.ex.*)" id="publicMethod"/>
<aop:around pointcut-ref="publicMethod" method="loggerAop"/>
</aop:aspect>
</aop:config>
<bean id="student" class="com.edu.ex.Student">
<property name="name">
<value>hongku_student</value>
</property>
<property name="age">
<value>26</value>
</property>
</bean>
<bean id="worker" class="com.edu.ex.Worker">
<property name="name">
<value>hongku_worker</value>
</property>
<property name="age">
<value>36</value>
</property>
<property name="job">
<value>developer</value>
</property>
</bean>
</beans>
namespace에 aop를 추가 한다.
LogAop.java
package com.edu.ex;
import org.aspectj.lang.ProceedingJoinPoint;
// proxy
public class LogAop {
// 경과시간 체크하는 공통기능 메소드
public Object loggerAop(ProceedingJoinPoint joinPoint) throws Throwable {
String signatureStr = joinPoint.getSignature().toShortString();
System.out.println(signatureStr + "is start.");
long st = System.currentTimeMillis();
try {
// 핵심기능 메소드 실행
Object obj = joinPoint.proceed();
return obj;
} finally {
long et = System.currentTimeMillis();
System.out.println(signatureStr + "is finished.");
System.out.println(signatureStr + " 경과시간 : " + (et - st));
}
}
}
공통기능(시간체크하는 기능)이 2번 호출 된다.
공통기능 실행 -> 핵심기능 실행 -> 공통기능 실행
▲ 결과 화면
시작 시간을 체크 (공통기능 1회 실행)
핵심기능 실행 (getInfo() 메소드)
끝나는 시간을 체크 (공통기능 2회 실행)
AOP 태그의 종류
-
<aop:before> : 메소드 실행전에 advice 실행
-
<aop:after-returning> : 정상적으로 메소드 실행 후에 advice 실행
-
<aop:after-throwing> : 메소드 실행둘 exception 발생시 advice 실행
-
<aop:after> : 메소드 실행중 exception이 발생해도 advice 실행
-
<aop:around> : 메소드 실행 전/후 및 exception 발생시 advice 실행
※ 이 글은 Seoul Wiz - '실전 Spring 강좌'를 요약하여 작성하였습니다.
'WEB > SpringMVC' 카테고리의 다른 글
SpringMVC :: 컨트롤러(Controller), Model, ModelAndView 사용법 (309) | 2018.03.15 |
---|---|
SpringMVC :: 스프링 MVC 기초, 스프링MVC 프로젝트 만들기 (301) | 2018.03.14 |
SpringMVC :: 상황에 따라서 개발환경 바꾸면서 실행하기 (974) | 2018.03.11 |
SpringMVC :: 프로퍼티 파일(property, properties)을 이용한 빈 생성 및 설정하기 (622) | 2018.03.11 |
SpringMVC :: 외부에 있는 파일을 이용해서 빈과 설정값을 set하는 방법 (1126) | 2018.03.11 |
최근댓글