deblog

AOP(Aspect Oriented Programming) 실습(3) 본문

IT/JAVA

AOP(Aspect Oriented Programming) 실습(3)

스콘_ 2021. 4. 17. 17:53
반응형

2021.04.17 - [분류 전체보기] - AOP(Aspect Oriented Programming) 구현(2)

 

AOP(Aspect Oriented Programming) 구현(2)

2021.04.17 - [IT/Spring] - AOP(Aspect Oriented Programming)란?(1) AOP(Aspect Oriented Programming)란?(1) AOP(관점 지향적인 프로그래밍) 문제를 바라보는 관점을 기준으로 프로그래밍하는 기법을 말한다...

deseul.tistory.com

이제 이클립스로 실습해보겠습니다.

환경구축(proxy 有)

src에 testpackage를 만든후 AOP_main java파일

(vo에 들어간 target클래스의 메서드와 연결할 xml를 표시.)

package springaop;

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

import springaop.z01_vo.Message;
import springdi.z01_vo.Person;

public class AOP_Main1 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		AbstractApplicationContext ctx 
		= new GenericXmlApplicationContext(
				"springaop\\container1.xml");
		Message msg = ctx.getBean("proxy",Message.class);
		msg.helloApp(); 
		// 프락시안에 있는 대상객체 Message의 helloApp() 수행될 때,
		// AOP안에

		ctx.close();
	}
}

적용할 coniainer1.xml을 만듭니다.(설명에서 acQuickStart.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop" 
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xmlns:p="http://www.springframework.org/schema/p"
   xmlns:c="http://www.springframework.org/schema/p"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:websocket="http://www.springframework.org/schema/websocket"
   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.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc.xsd     
        http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd
         http://www.springframework.org/schema/websocket
      http://www.springframework.org/schema/websocket/spring-websocket.xsd" >

    <!-- 
    # AOP프로그램 처리
    1. 대상이 되는 target 클래스 선언..
    2. 관심모듈(AOP) 클래스 선언
    3. Advisor(pointcut + advice) 처리..
    4. Proxy 클래스 선언.
	 -->
	 <!-- 1. 대상클래스 -->
	<bean id="messgeImpl" class="springaop.z01_vo.Message">
      <property name="name">
          <value>홍길동</value>
      </property>
	</bean>

	<!-- 2. 관심모듈(AOP)클래스선언: 해당 대상객체가 수행될 때, 처리할 내용 -->
	<bean id="logging" class="springaop.z01_vo.Logging"/>

	<!-- 3. Advisor = pointcut(시점) + advice(처리할 내용) -->
	<bean id="advisor"
	class="org.springframework.aop.support.DefaultPointcutAdvisor">
		<!-- 1) 시점을 지정 -->
		<property name="pointcut">
			<bean class="org.springframework.aop.support.JdkRegexpMethodPointcut">
				<property name="pattern">
					<value>.*.helloApp</value> 
					<!-- helloApp 메서드가 수행될때..! -->
				</property>
			</bean>
		</property>
		<!-- 2) 해당 시점이 수행될 때, 처리할 내용. -->
		<property name="advice" ref="logging"/> <!--  로그파일 실행. -->
	</bean>

	<!-- 3.Proxy 클래스선언 -->
	<bean id="proxy"
	class="org.springframework.aop.framework.ProxyFactoryBean">
	<!-- 대상지정 -->
	<property name="target">
		<ref bean="messgeImpl"/>
	</property>
	<!-- advisor선언 -->
	<property name="interceptorNames">
		<list>
			<value>advisor</value>
		</list>
	</property>
	</bean>
</beans>  

Message.java

대상 클래스 (targetClass)

package springaop.z01_vo;

// 대상클래스 지정(targetClass)
public class Message {
	private String name;
	public void setName(String name) {
		this.name = name;
	}
	// 처리할 내용
	public void helloApp() {
		// 5초후 수행
		try {
			Thread.sleep(5000);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		System.out.println(name+"님 안녕하세요.");
	}
}

 

vo안에 있는 Logging.java 

message에 있는 helloApp메소드가 처리될때 수행할 클래스(설명에서 Profile.java)

package springaop.z01_vo;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.util.StopWatch;

// springAOP.z01_vo.Logging
// aop 처리할 메서드 선언.
public class Logging implements MethodInterceptor{

	@Override
	public Object invoke(MethodInvocation invoke) throws Throwable {
		// TODO Auto-generated method stub
		// MethodInvocation : 대상 객체에 대한 정보를 가지고 올 수 있음.
		// 1. getMethod.getName() : 대상 객체의 메서드 이름
		// 2. proceed() : 수행되는 대상 객체
		// 처리할 내용 : 해당 기능 객체의 메서드가 수행하는 시간을 처리..
		// 1. 시간 측정을 위한 StopWatch 클래스 선언..
		//		.start() : 스탑워치의 시작시간 설정.
		// 		.stop()N : 스탑워치의 마지막 시간 설정
		// 		.getTotalTimeMillis() : 위에 수행한 시작메서드와 마지막메서드
		// 		 를 통해 수행한 시간을 1/1000초 단위로 가져온다.

		String methodName = invoke.getMethod().getName(); // 어떤 메서드가 수행되는지
		System.out.println("대상객체의 수행메서드(시작)"+methodName);
		StopWatch sw = new StopWatch();
		// 시작시간 check
		sw.start();


		Object obj = invoke.proceed(); // 대상 객체의 수행 처리 process
		// 수행후 시작 check
		sw.stop();

		System.out.println("대상객체의 수행메서드(종료):"+methodName);
		System.out.println("대상객체의 수행시간:"
						+(sw.getTotalTimeMillis()/1000.0)+"초");

		return obj;
	}

}

AOP_main1 실행결과

 

환경구축(proxy 無)

src에 testpackage를 만든후 AOP_main java파일

(vo에 들어간 target클래스의 메서드와 연결할 xml를 표시.)

package springaop;

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

import springaop.z01_vo.Message;
import springdi.z01_vo.Person;

public class AOP_Main2 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		AbstractApplicationContext ctx 
		= new GenericXmlApplicationContext(
				"springaop\\container2.xml");
		Message msg = ctx.getBean("target",Message.class);
		msg.helloApp();
		ctx.close();
	}
}

container2.xml

targetClass선언 aspectClass도선언

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop" 
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xmlns:p="http://www.springframework.org/schema/p"
   xmlns:c="http://www.springframework.org/schema/p"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:websocket="http://www.springframework.org/schema/websocket"
   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.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc.xsd     
        http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd
         http://www.springframework.org/schema/websocket
      http://www.springframework.org/schema/websocket/spring-websocket.xsd" >

	<!-- Proxy없이 바로처리 
	
	1. 대상객체 선언.
	2. advise 선언
	3. adviser 선언 : adivise와 pointcut 선언
	
	-->
	<bean id="target" class="springaop.z01_vo.Message" p:name="★송강★"/>
	<!--  target이 시행될때 aspect도 같이 수행되는 로직 -->
	<bean id="aspect" class="springaop.z01_vo.Logging2"></bean>
	<aop:config> <!-- aop:config에서 proxy없이 선언이 가능 -->
		<!-- aspect 선언 -->
		<aop:aspect id="aspectClass" ref="aspect">

		<!-- pointcut 시점 -->
		<aop:pointcut expression="execution(public * *())" id="point"/>

		<!-- advise의 종류(이전, 이후, 실행중간..) -->
		<aop:around method="logAround" pointcut-ref="point"/> 
		<!--  수행하는 중간(Logging2클래스에 선언해놨던 logAround )-->

		</aop:aspect>
	</aop:config>
</beans>  

vo안에 있는 Logging.java

message에 있는 helloApp메소드가 처리될때 수행할 클래스(설명에서 Profile.java)

package springaop.z01_vo;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// springaop.z01_vo.Logging2
// proxy없이 aop

// aop 처리할 메서드 선언.
public class Logging2{

	// 로그 처리 기능 클래스 선언
	private static final  Logger logger=LoggerFactory.getLogger(Logging2.class);
	// 1. 이전 시점
	public void logBefore(JoinPoint joinPoint) {
		logger.debug("logBefore()");
	}
	// 2. 이후 시점
	public void logAfter(JoinPoint joinPoint) {
		logger.debug("logAfter()");
	}
	// 3. 수행하는 중간에 처리
	public Object logAround(ProceedingJoinPoint jointPoint) throws Throwable {
		// 1) jointPoint 객체 리턴(대상)
		Object thisObj = jointPoint.getTarget();

		// 2) 대상객체의 이름, 메서드명, 매개변수..
		String className = thisObj.getClass().getName(); // 대상객체의 이름
		String methodName = jointPoint.getSignature().getName(); // 메서드명
		Object[] args = jointPoint.getArgs(); // 매개변수

		//3) 시간 측정
		long currentTime = System.currentTimeMillis();
		logger.debug("#############");
		logger.debug("###시 작#####");
		logger.debug("[class명]:"+className);
		logger.debug("[methodName]:"+ methodName+"()");

		Object returnObj = jointPoint.proceed();
		// 수행처리. 예외처리는 throws Throwable

		logger.debug("#######수행 이후########");
		logger.debug("[class명]:"+className);
		logger.debug("[methodName]:"+ methodName+"()");
		logger.debug("소요시간:"+
					(System.currentTimeMillis()-currentTime)+"ms");

		logger.debug("#######종료########");

		return returnObj;
	}
}

 

 

대상클래스 (message클래스)

AOP_main2. 실행결과

Comments