본문 바로가기
자바과정/스프링

스프링 실습예제(Xml 방식의 AOP)

by Parkej 2021. 4. 8.

AOP란

더보기
AOP (API) - 방법론
- AOP를 구현할때 스프링이 도움을 줌
- 스프링이 지원해주는 범주 내에서 AOP 방법론으로 프로그램을 만들게 되면 어떤 도움을 받을 수 있을까 ?

Aspect Oriented Programming (AOP)
사용자 -> 주 업무 로직
- 기존엔 사용자가 원하는 업무 기반의 로직만 관심만 가졌음
- 프로그램을 만들땐 사용자의 업무를 분석하고, 거기에 대한 로직을 구현하려고 많은 서비스를 구현했다.
- 사실 느끼지못한 코드가 여기에 들어갔음
- 사용자 요구사항말고 이것을 수반하기위해 작성하다보니까 그 외의 코드가 들어가게됨.
- 코드 : 사용자가 요구했던 업무적인게 아니라,
- 개발자/관리자가 프로그램을 구현하기 위해서든 테스트하기 위해서든 필요한 코드들이 존재하게 됨.
- 이러한 코드들은 주 업무 로직에 필요한 코드들이 아니라 개발자/관리자가 필요에 따라 코드들을 껴놓은것
- 사용자는 이런걸모름 만들라고 한적 없음.
- 이건 개발자/운영자가 자신들이 쓰기위해 껴놓는 부가적인 코드들임
- 이것을 보조업무라고 표현한다.
- 주 업무만 대우해줬지만 개발자/운영자가 넣게되는 코드들도 관점이 다른 업무라고 봄
- 사용자 관점으로 봤떤것이 지금까지 객체지향으로 잘 만들어 졌다면, 추가로 만들게 되는 로직을 개발자/운영자 관점에서 넣어야하는 로직이 있어야함.
- 이걸 관점 지향 업무라 함. (객체지향보다 큰 개념) - 주 업무 로직 : 객체지향, 그 외의 것까지 포함 : 관점 지향

 

AOP를 하기위한 구성
- AOP API를 Maven에 등록
- porm.xml
- 파일 구성 
- resource : appCTX.xml
- java : Worker, Student, LogAop, MainClass.java

 

- AOP 용어
Aspect : 공통 기능
Advice : Aspect의 기능 자체 JoinPoint Advice를 적용해야 되는 부분(ex 필드..)
Pointcut : joinpoint의 부분으로 실제로 Advice가 적용된 부분
Weaving : Advice를 핵심 기능에 적용 하는 행위

- AOP 태그 종류
<aop:before> : 메소드 실행 전에 advice 실행
<aop:after-returning> : 정상적으로 메소드 실행 후에 advice 실행
<aop:after-throwing> : 메소드 실행중 exception 발생시 advice 실행
<aop:after> : 메소드 실행중 exception이 발생하여도 advice 실행
<aop:around> : 메소드 실행 전/후 및 exception 발생시 advice 실행

 

 

- porm.xml에 AOP api 등록
<!-- AOP -->
  <dependency>
	<groupId>org.aspectj</groupId>
	<artifactId>aspectjweaver</artifactId>
	<version>1.7.4</version>
  </dependency>

 

 

 

데이터 클래스 생성
- Student, Worker (java)

 

student.java

 

package com.javalec.ex;

public class Student {
	private String name;
	private int age;
	private int gradeNum;
	private int classNum;
	
	public void getStudentInfo() {
		System.out.println("이름 : " + getName());
		System.out.println("나이 : " + getAge());
		System.out.println("학년 : " + getGradeNum());
		System.out.println("반 : " + getClassNum());
		
	}

	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 int getGradeNum() {
		return gradeNum;
	}

	public void setGradeNum(int gradeNum) {
		this.gradeNum = gradeNum;
	}

	public int getClassNum() {
		return classNum;
	}

	public void setClassNum(int classNum) {
		this.classNum = classNum;
	}
	
}

 

 

 

 

Worker.java

 

package com.javalec.ex;

public class Worker {
	private String name;
	private int age;
	private String job;

	public void getWorkerInfo() {
		System.out.println("이름 : " + getName());
		System.out.println("나이 : " + getAge());
		System.out.println("직업 : " + getJob());
	}

	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;
	}
	
}

 

 

메인 클래스 생성(출력하기 위한 클래스)
MainClass.java

 

 

 

package com.javalec.ex;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class MainClass {
	public static void main(String[] args) {
	      AbstractApplicationContext ctx
	      = new GenericXmlApplicationContext("classpath:appCTX.xml");
	      
	      Student student = ctx.getBean("student", Student.class);
	      student.getStudentInfo();
	      
	      Worker worker = ctx.getBean("worker", Worker.class);
	      worker.getWorkerInfo();

	}
}

 


본격적인 AOP 사용 부분 클래스와 xml
appCTX.xml

 

- namespace -> aop 체크

구조
// AOP
// 주 업무 (메인 코드)
// AOP

 

<?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.1.xsd">

	<!-- 공통기능 stu하고 work에 똑같이 적용시키고 싶음. LogAop 의 loggerAop 메소드-->
	<bean id="logAop" class="com.javalec.ex.LogAop"></bean>
	<aop:config >
		<aop:aspect id ="logger" ref="logAop">
			<aop:pointcut expression="within(com.javalec.ex.Student)" id="publicM"/>
			<aop:around method="loggerAop" pointcut-ref="publicM"/>
		</aop:aspect>
		
		<aop:aspect id="logger" ref="logAop">
			<aop:pointcut expression="within(com.javalec.ex.*)" id="publicM" />
			<aop:before method="beforeAdvice" pointcut-ref="publicM" />
		</aop:aspect>

		<aop:aspect id="logger" ref="logAop">
			<aop:pointcut expression="within(com.javalec.ex.*)" id="publicM" />
			<aop:after-returning method="afterReturningAdvice" pointcut-ref="publicM" />
		</aop:aspect>

		<aop:aspect id="logger" ref="logAop">
			<aop:pointcut expression="within(com.javalec.ex.*)" id="publicM" />
			<aop:after-throwing method="afterThrowingAdvice" pointcut-ref="publicM" />
		</aop:aspect>

		<aop:aspect id="logger" ref="logAop">
			<aop:pointcut expression="within(com.javalec.ex.*)" id="publicM" />
			<aop:after method="afterAdvice" pointcut-ref="publicM" />
		</aop:aspect>
	</aop:config>

	<bean id="student" class="com.javalec.ex.Student">
		<property name="name" value="ppp" />
		<property name="age" value="10" />
		<property name="gradeNum" value="1" />
		<property name="classNum" value="3" />
	</bean>
	<bean id="worker" class="com.javalec.ex.Worker">
		<property name="name" value="pep" />
		<property name="age" value="15" />
		<property name="job" value="stu" />
	</bean>



</beans>

 

 

LogAop.java

 

// AOP
proceed(); // 핵심기능을 부르는 것임.
// AOP

 

 

package com.javalec.ex;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

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));
		}
	}

	public void beforeAdvice(JoinPoint joinPoint) {
		System.out.println("beforeAdvice()");
	}

	public void afterReturningAdvice() {
		System.out.println("afterReturningAdvice()");
	}

	public void afterThrowingAdvice() {
		System.out.println("afterThrowingAdvice()");
	}

	public void afterAdvice() {
		System.out.println("afterAdvice()");
	}
}

 


 

ThrowingAdvice를 제외한 모든 결과가 출력됨.

 

반응형

댓글