AOP 방법론으로 프로그래밍하면 어떤 도움을 받을 수 있는지 알아보기

    AOP(Aspect Oriented Programming) 이해하기

     

    관점 지향 프로그래밍

     

    사용자 요구사항을 수반하기 위해서 주 업무 로직이 아닌 필요한 코드가 들어가게 된다.

    사용자는 모르는 내용으로 개발자가 개발을 위해서 운영자가 운영을 위해서 넣게 된다.

    사용자가 바라보았던 내용 - > 주 업무

    운영자의 관점으로 봤던 내용 추가 -> 새로운 로직 

    더 큰 단위로 관점을 분리하고 결합시켜서 프로그램을 만들 것인가 하는 방법론

     

    Concern 

    Primary(Core) Concern과 Cross-cutting Concern

    사용자의 요구사항을 수반하기 위해서 필요한 로직 -> Cross-cutting Concern

     

    로그 처리

    보안 처리

    트랜잭션 처리

     

    Core Concern은 주 업무만 만들고

    Cross-cutting Concern과 관련된 Concern을 Core Concern에 두지 않고 따로 proxy에 두고 호출

    겉 업무를 따로 분리해서 겉 업무를 Core Concern에서 분리사용

     

    Spring에서 AOP를 이용하면 코드의 변경과 수정의 문제가 Spring DI로 해결된다.


    AOP 코드 구현하기

    총점과 평균을 구하는 예제

    업무단위 만들어주기

     

    업무 호출하기

    사용자가 요구하는 기능 수준에서 total을 출력했다.

    개발자 관점에서 새로운 관점을 추가해야 한다. -> 얼마나 느린지 알아보기 위해 시간 체크 코드 넣기 

     

    겉 업무에 해당하는 관점이 다른 사람들의 필요에 의해 만들어지는 코드이다.

    NewlecExam.java

    package spring.aop.entity;
    
    public class NewlecExam implements Exam {
    	
    	private int kor;
    	private int eng;
    	private int math;
    	private int com;
    	
    	//생성자
    	public NewlecExam() {
    		// TODO Auto-generated constructor stub
    	}
    	
    	//생성자 오버로드
    	public NewlecExam(int kor, int eng, int math, int com) {
    		super();
    		this.kor = kor;
    		this.eng = eng;
    		this.math = math;
    		this.com = com;
    	}
    
    	public int getKor() {
    		return kor;
    	}
    
    	public void setKor(int kor) {
    		this.kor = kor;
    	}
    
    	public int getEng() {
    		return eng;
    	}
    
    	public void setEng(int eng) {
    		this.eng = eng;
    	}
    
    	public int getMath() {
    		return math;
    	}
    
    	public void setMath(int math) {
    		this.math = math;
    	}
    
    	public int getCom() {
    		return com;
    	}
    
    	public void setCom(int com) {
    		this.com = com;
    	}
    
    	@Override
    	public int total() {
    //		long start = System.currentTimeMillis();
    		int result = kor+eng+math+com;
    		
    		//일부러 시간을 느리게 해준다.
    		try {
    			Thread.sleep(200);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} 
    		
    //		long end = System.currentTimeMillis();
    //		
    //		String message = (end - start) + "ms 시간이 걸렸습니다.";
    //		System.out.println(message);
    		
    		return result;
    	}
    
    	@Override
    	public float avg() {
    		
    		float result = total() / 4.0f;
    		
    		return result;
    	}
    
    	@Override
    	public String toString() {
    		return "NewIecExam [kor=" + kor + ", eng=" + eng + ", math=" + math + ", com=" + com + "]";
    	}
    	
    
    }

    하지만 지금 하는 것은 옛날 버전으로 코드 안에 작성하지 않고 불러오는 방법을 사용해야 한다.

     

    순수 자바로  AOP 구현하기

    Proxy 도구 사용하기

     

    겉 업무를 필요에 따라 사용할 수 있다. -> AOP 방식

    Program.java

    package spring.aop;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    import spring.aop.entity.Exam;
    import spring.aop.entity.NewlecExam;
    
    public class Program {
    	
    	public static void main(String[] args) {
    		
    		Exam exam = new NewlecExam(1,1,1,1);
    		
    		//Proxy가 겉업무를 포함해서 exam을 호출
    		//newProxyInstance(실질적인객체, 인터페이스 정보(배열), 겉업무를 추가시키는 부분 InvocationHandler())
    		Exam proxy = (Exam)Proxy.newProxyInstance(NewlecExam.class.getClassLoader(),
    				new Class[] {Exam.class},
    					new InvocationHandler() {
    						
    						@Override
    						public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    							
    							long start = System.currentTimeMillis();
    							
    							//method.invoke(업무객체, )
    							Object result = method.invoke(exam, args);
    							
    							long end = System.currentTimeMillis();
    							String message = (end - start) + "ms 시간이 걸렸습니다.";
    							System.out.println(message);
    							
    							return result;
    						}
    					}
    				);
    		
    		
    		System.out.printf("total is %d\n", proxy.total());
    		System.out.printf("avg is %f\n", proxy.avg());
    	}
    
    }


    스프링으로 AOP 구현하기

    출처 : https://www.programmersought.com/article/644854133/

    모든 설정을 xml에서 처리 Spring Around Advice

    3가지 결합되는 관계 설정

    target

    LogAroundAdvice

    proxy

     

    setting.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:p="http://www.springframework.org/schema/p"
    	xmlns:util="http://www.springframework.org/schema/util"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
    		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
    	
    	
    	<bean id="target" class="spring.aop.entity.NewlecExam" p:kor="1"  p:eng="1"  p:math="1"  p:com="1"/>
    	<bean id="logAroundAdvice" class="spring.aop.advice.LogAroundAdvice" />
    	<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    		<property name="target" ref="target" />
    		<property name="interceptorNames">
    			<list>
    				<value>logAroundAdvice</value>
    			</list>
    		</property>
    	</bean>
    	
    </beans>

     

    LogAroundAdvice.java

    package spring.aop.advice;
    
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    
    public class LogAroundAdvice implements MethodInterceptor {
    
    	@Override
    	public Object invoke(MethodInvocation invocation) throws Throwable {
    		long start = System.currentTimeMillis();
    		
    		Object result = invocation.proceed();
    		
    		long end = System.currentTimeMillis();
    		String message = (end - start) + "ms 시간이 걸렸습니다.";
    		System.out.println(message);
    		
    		return result;
    	}
    
    }

     

    Program.java

    package spring.aop;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import spring.aop.entity.Exam;
    import spring.aop.entity.NewlecExam;
    import spring.di.NewlecDIConfig;
    
    public class Program {
    	
    	public static void main(String[] args) {
    		
    		ApplicationContext context = 
    				//new AnnotationConfigApplicationContext(NewlecDIConfig.class);		
    				new ClassPathXmlApplicationContext("spring/aop/setting.xml");
    		
    		Exam proxy = (Exam)context.getBean("proxy");
    		
    		System.out.printf("total is %d\n", proxy.total());
    		System.out.printf("avg is %f\n", proxy.avg());
    		
    		
    		/*
    		Exam exam = new NewlecExam(1,1,1,1);
    		
    		
    		//Proxy가 겉업무를 포함해서 exam을 호출
    		//newProxyInstance(실질적인객체, 인터페이스 정보(배열), 겉업무를 추가시키는 부분 InvocationHandler())
    		Exam proxy = (Exam)Proxy.newProxyInstance(NewlecExam.class.getClassLoader(),
    				new Class[] {Exam.class},
    					new InvocationHandler() {
    						
    						@Override
    						public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    							
    							long start = System.currentTimeMillis();
    							
    							//method.invoke(업무객체, )
    							Object result = method.invoke(exam, args);
    							
    							long end = System.currentTimeMillis();
    							String message = (end - start) + "ms 시간이 걸렸습니다.";
    							System.out.println(message);
    							
    							return result;
    						}
    					}
    				);
    		*/
    		
    		
    	}
    
    }

     

     

    같은 기능을 한다. 왼쪽은 지워줌(주석처리)


    Spring xml 방식 AOP 

    주 업무 내용만 동작하게 하기 - 설정만으로 로그를 뺐다 붙였다 할 수 있다.

     

    • 네이버 블러그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기
    loading