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>
'개발자 > 국비지원 SW' 카테고리의 다른 글
국비지원 101일차 - Spring 체크된 값만 받기, 주문처리 (0) | 2020.09.16 |
---|---|
국비지원 100일차 - VueJS 예제(반복,조건,bind,filter), computed, v-model, CRUD(Create) (0) | 2020.09.15 |
국비지원 98일차 - Spring JSON데이터 생성, AOP VueJS dynamic, v-for (0) | 2020.09.11 |
국비지원 97일차 - VueJS directive (0) | 2020.09.10 |
국비지원 96일차 - 온라인강의 환경설정, Vue.JS, MVVM패턴, Vue객체 (0) | 2020.09.09 |