pointcut표현식

ASPECT어노테이션 기반 AOP
1. @Aspect를 이용해서 Aspect클래스를 구현 이 때 Advice를 구현한 메소드와 Pointcut을 포함한다.
2. XML설정에서 를 설정한다. Cf>(스프링은 객체를 생성할 때 해당 객체와 연관된 것을 연결 시켜주기 위해서 프락시 패턴을 사용한다.) @Aspect어노테이션을 이용할 경우 XML설정 파일에서 Pointcut을 설정하는 것이 아니라 클래스에서 Pointcut 을 정의한다.
3. Test클래스 작성

CommonAspect.java

package ex02;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class CommonAspect {

	@Pointcut("execution(* ex02.ServiceImpl.insertData(..))")
	public void logging() {
		//@Pointcut이 적용되는 메소드는 반환타입이 void여야한다.
	}
	
	//@Before("logging()")
	public void trace1(JoinPoint p) {
		Signature sign = p.getSignature();
		System.out.println("====before====["+sign.toLongString()+"]=====");
	}
	
	//@After("logging()")
	public void trace2(JoinPoint p) {
		Signature sign = p.getSignature();
		System.out.println("====after====["+sign.toLongString()+"]=====");
	}
	//@AfterReturning(value="logging()",returning = "result")
	public void trace3(JoinPoint p,Integer result) {
		Signature sign = p.getSignature();
		System.out.println("====after returning====["+sign.toLongString()+"]=====반환값: "+result);
	}
	//@AfterThrowing(value="logging()",throwing="ex")
	public void trace4(JoinPoint p,Exception ex) {
		Signature sign = p.getSignature();
		System.out.println("====after throwing====["+sign.toLongString()+"]=====예외: "+ex);
	}
	@Around("logging()")
	public Integer trace5(ProceedingJoinPoint jp) {
		Signature sign = jp.getSignature();
		System.out.println("====around(before)====["+sign.toShortString()+"] start=====");
		Integer n=0;
		long start=System.nanoTime();
		long end=0;
		try {
			n = (Integer)jp.proceed(); //ServiceImpl의 insertData()호출
			end=System.nanoTime();
			return n;
		} catch (Throwable e) {
			e.printStackTrace();
			return null;
		}finally {
			System.out.println("====around(after)====["+sign.toShortString()+"] end=====");
			System.out.println(sign.toShortString()+"메소드 실행 시간: "+(end-start)+"ns");
		}
	}
}

aop.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">


	<!-- 어노테이션을 통해 aop를 설정하려면 aop:aspectj-autoproxy 엘리먼트를 등록 -->
	<aop:aspectj-autoproxy/>
	
	<!-- Aspect 공통관심 빈-->
	<bean id="common" class="ex02.CommonAspect"/>
	
	
	<!-- Target 핵심로직 빈 -->
	<bean id="obj2" class="ex02.ServiceImpl"/>
	
	
</beans>

SpringAopTest2

package ex02;

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

public class SpringAopTest2 {

	public static void main(String[] args) {
		ApplicationContext ctx= new GenericXmlApplicationContext("classpath:ex02/aop.xml");
		Service svc= ctx.getBean("obj2",Service.class);
		svc.insertData("게시길을 등록합니다.");
	}

}

Interceptor

MethodInterceptor
메소드 호출용 어라운드 어드바이스의 표준 인터페이스 이 객체를 이용해서 메소드 호출이 실행되는 시점을 제어할 수 있다.

AroundAdvice

package ex03;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class AroundAdvice implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		System.out.println("AroundAdvice: "+invocation.getMethod()+"메소드 호출 전(before)");
		Object obj = invocation.proceed();
		System.out.println("AroundAdvice: "+invocation.getMethod()+"메소드 호출 후(after)");
		return obj;
	}

}

SpringAOPTest

package ex03;

import org.springframework.aop.framework.ProxyFactory;

public class SpringAOPTest3 {
	
	public static void main(String[] args) {
		ServiceImpl target = new ServiceImpl();//타겟 핵심
		AroundAdvice common = new AroundAdvice();//어드바이스(공통관심사항)
		
		ProxyFactory pf = new ProxyFactory();
		pf.addAdvice(common);
		pf.setTarget(target);
		//대리객체(Proxy객체)를 만들어 타겟과 어드바이스를 엮는다.
		
		ServiceImpl svc = (ServiceImpl)pf.getProxy();
		svc.insertData("게시글을 작성 했습니다.");
	}
	
}

Interceptor 구현
컨트롤러가 실행되기 전에 사전 처리할 작업이 있다면 스프링에서는 인터셉터로 구현한다
1. 인터셉터 구현하기
[1] HandlerInterceptor 인터페이스를 상속받아 구현하기
[2} HandlerInterceptorAdapter추상클래스를 상속받아 구현하기
2. servlet-context.xml에 인터셉터 등록하고 매핑 정보 설정하기

LoginCheckInterceptor

package com.tis.common.interceptor;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.tis.domain.UserVO;

import lombok.extern.log4j.Log4j;

/*
 * Interceptor
 * -컨트롤러가 실행되기 전에 사전 처리할 작업이 있다면 스프링에서는 인터셉터로 구현한다.
 * 1. 인터셉터 구현하기
 * 	[1] HandlerInterceptor인터페이스를 상속받아 구현하기
 * 	[2] HandlerInterceptorAdapter추상클래스를 상속받아 구현하기
 * 2. servlet-context.xml에 인터셉터 등록하고 매핑 정보 설정하기
 * */

@Log4j
public class LoginCheckInterceptor implements HandlerInterceptor{@Override
	public boolean preHandle(HttpServletRequest req, HttpServletResponse response, Object handler) //preHandle : 사전
			throws Exception {
		log.info("LoginCheckInterceptor...preHandle()");
		
		HttpSession ses=req.getSession();
		UserVO loginUser=(UserVO)ses.getAttribute("loginUser");
		if(loginUser!=null) return true; //로그인 했다면 true를 반환한다. > controller로 전달됨
		
		//로그인 하지 않았다면 ==>false를 반환
		String str="로그인 해야 이용할 수 있어요";
		String loc=req.getContextPath()+"/index";
		
		String viewName="/WEB-INF/views/msg.jsp";
		
		//req에 저장
		req.setAttribute("message", str);
		req.setAttribute("loc", loc);
		
		RequestDispatcher disp=req.getRequestDispatcher(viewName);
		disp.forward(req, response);
		
		return false;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, //postHandle : 사후
			ModelAndView modelAndView) throws Exception {
		log.info("LoginCheckInterceptor...postHandle()");
		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)//afterCompletion :완료된 후에
			throws Exception {
		log.info("LoginCheckInterceptor...afterCompletion()");
		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
	}

	
}

servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<!-- 정적인 파일들(css,js,images...등)을 dispatcher servlet이 매핑정보를 찾아 컨트롤러를 실행시키지 못하도록...리소스로 인식하도록 등록해주자. -->
	<resources mapping="/resources/**" location="/resources/" />
	<resources mapping="/images/**" location="/images/" />
	<resources mapping="/css/**" location="/css/" />
	<resources mapping="/js/**" location="/js/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<context:component-scan base-package="com.tis.myshop, com.tis.test, com.tis.service, com.tis.persistence" />
	<context:component-scan base-package="com.tis.common.util, com.tis.common"/>
	
	<!-- Interceptor 설정=============================== -->
	<interceptors>
		<interceptor> 
			<mapping path="/user/**"/>
			<mapping path="/admin/**"/>
			<beans:bean class="com.tis.common.interceptor.LoginCheckInterceptor"/>
		</interceptor>
	</interceptors>
</beans:beans>

+ Recent posts