// 1. 스프링 API를 이용한 AOP 기능 실습.
1. AOPTest.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="calcTarget" class="com.spring.ex01.Calculator"/> // 주기능 - 타깃 클래스를 빈으로 지정
<bean id="logAdivce" class="com.spring.ex01.LoggingAdvice"/> // 공통기능 - 로그기능을 하는 어드바이스를 지정
//스프링 프레임워크에서 제공하는 ProxyFactoryBean을 이용해 타깃과 어드바이스를 엮어줌.
<bean id="proxyCal" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="calcTarget"/> // 타깃 빈을 calcTest 빈으로 지정
// 스프링의 ProxyFactoryBean의 interceptorNames 속성에 logAdvice를 어드바이스 빈으로 설정하여
// 타깃 클래스의 메소드 호출시 logAdvice를 실행.
<property name="interceptorNames">
<list>
<value>logAdivce</value>
</list>
</property>
</bean>
</beans>
2. Calculator.java
package com.spring.ex01;
public class Calculator {
public void add(int x, int y) {
int result= x + y;
System.out.println("결과: " + result);
}
public void subtract(int x, int y) {
int result= x - y;
System.out.println("결과: " + result);
}
public void multiply(int x, int y) {
int result= x * y;
System.out.println("결과: " + result);
}
public void divide(int x, int y) {
int result= x / y;
System.out.println("결과: " + result);
}
}
3. LoggingAdvice.java
package com.spring.ex01;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
// 인터페이스 MethodInterceptor를 구현해 어드바이스 클래스를 만듬.
public class LoggingAdvice implements MethodInterceptor{
public Object invoke(MethodInvocation invocation) throws Throwable{
System.out.println("[메소드 호출 전 : LogginAdivce");
System.out.println(invocation.getMethod() + "메소드 호출 전");
Object object = invocation.proceed(); // invocation을 이용해 메소드를 호출.
System.out.println("[메소드 호출 후 : LogginAdivce");
System.out.println(invocation.getMethod() + "메소드 호출 후");
return object;
}
}
4. CalcTest.java
package com.spring.ex01;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CalcTest {
public static void main(String[] args) {
// AOPTest.xml을 읽어들여 빈을 생성.
ApplicationContext context = new ClassPathXmlApplicationContext("AOPTest.xml");
Calculator cal = (Calculator) context.getBean("proxyCal"); // id가 proxyCal인 빈에 접근.
// proxyFactoryBean은 AOP설정이 반영된 Target객체를 리턴한다.
// 메소드 호출 전후에 어드바이스 빈이 적용됨.
cal.add(100, 20);
System.out.println();
cal.subtract(100, 20);
System.out.println();
cal.multiply(100, 20);
System.out.println();
cal.divide(100, 20);
}
}
// XML 스키마 기반 AOP 퀵 스타트 실습
1. MainQuickStart.java
package spring.apo.ex01;
import org.springframework.context.support.GenericXmlApplicationContext;
import spring.apo.ex01.component.ReadArticleService;
public class MainQuickStart {
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:acQuickStart.xml");
ReadArticleService readArticleService = ctx.getBean(ReadArticleService.class);
readArticleService.read(1);
ctx.close();
}
}
2. ProfilerAdvice.java
package spring.apo.ex01.advice;
import org.aspectj.lang.ProceedingJoinPoint;
// Aound Advice
// 다른 advice는 대상객체 호출을 spring FW이 실행
public class ProfilerAdvice {
// ProceedingJoinPoint joinPoint 파라미터이면 -> Around Advice이고,
public Object trace(ProceedingJoinPoint joinPoint) throws Throwable {
String signatureString = joinPoint.getSignature().toShortString();
System.out.println(signatureString + " 시작");
long start = System.currentTimeMillis();
try {
// Around Advice이면, proceed() 메소드 제공한다.
Object result = joinPoint.proceed(); // aspect가 적용될 대상 객체 호출
return result;
} finally {
long finish = System.currentTimeMillis();
System.out.println(signatureString + " 종료");
System.out.println(signatureString + " 실행 시간 : " + (finish - start) + "ms");
}
}
}
3. asQuickStart.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:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<!-- 공통 기능을 제공할 클래스를 빈으로 등록 -->
<bean id="profiler" class="spring.apo.ex01.advice.ProfilerAdvice" />
<!-- Aspect 설정: Advice를 어떤 Pointcut에 적용할 지 설정 -->
<aop:config>
<aop:aspect id="traceAspect" ref="profiler">
// Aspect J의 표현식
<aop:pointcut id="publicMethod" expression="execution(public * spring.apo.ex01..*(..))" />
// pointcut 이라는 호출할 메소드의 범위를 결정하고 / * - 모든 파라미터를 가진 / (..) - 하위 패키지까지 포함.
<aop:around pointcut-ref="publicMethod" method="trace" />
// around - 호출시점 / trace - 공통기능
</aop:aspect>
</aop:config>
<bean id="readArticleService" class="spring.apo.ex01.component.ReadArticleServiceImpl">
<property name="articleDao" ref="articleDao" />
</bean>
<bean id="articleDao" class="spring.apo.ex01.component.ArticleDaoImpl" />
</beans>
// @Aspect 애노테이션 기반 AOP 퀵 스타트
1. MainQuickStart2.java
package spring.apo.ex02;
import spring.apo.ex02.component.ReadArticleService;
import org.springframework.context.support.GenericXmlApplicationContext;
public class MainQuickStart2 {
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:acQuickStart2.xml");
ReadArticleService readArticleService = ctx.getBean(ReadArticleService.class);
readArticleService.read(1);
ctx.close();
}
}
2. ProfilingAspect.java
package spring.apo.ex02.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class ProfilingAspect {
@Pointcut("execution(public * spring.apo.ex02..*(..))")
private void profileTarget() {
}
@Around("profileTarget()") // profileTarget()의 pointcut 정보를 쓰겠다.
public Object trace(ProceedingJoinPoint joinPoint) throws Throwable{
String signatureString = joinPoint.getSignature().toShortString();
System.out.println(signatureString + " 시작");
long start = System.currentTimeMillis();
try {
Object result = joinPoint.proceed(); // 타겟의 메소드 호출.
return result;
} finally {
long finish = System.currentTimeMillis();
System.out.println(signatureString + " 종료");
System.out.println(signatureString + " 실행 시간 : " +
(finish - start) + "ms");
}
}
}
3. asQuickStart2.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:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<aop:aspectj-autoproxy /> // proxy를 자동으로 호출.
<!-- Aspect 클래스를 빈으로 등록 -->
<bean id="performanceTraceAspect" class="spring.apo.ex02.aspect.ProfilingAspect" />
<bean id="readArticleService" class="spring.apo.ex02.component.ReadArticleServiceImpl">
<property name="articleDao" ref="articleDao" />
</bean>
<bean id="articleDao" class="spring.apo.ex02.component.ArticleDaoImpl" />
</beans>
@Pointcut 메소드 사용시 입력방법
- 같은 클래스 : 메소드 이름
- 같은 패키지 : 클래스명.메소드이름
- 다른 패키지 : 패지키명.클래스명.메소드이름
// 스프링 애너테이션 이용해 URL 요청 실습
1.action-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--<property name="prefix" value="/WEB-INF/views/test/" /> -->
<property name="prefix" value="/WEB-INF/views/test/" />
<property name="suffix" value=".jsp" />
</bean>
// 클래스 레벨에 @RequestMapping 처리
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
// 메소드 레벨에 @RequestMapping 처리
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<context:component-scan base-package="com.spring" /> // com.spring 패키지에 존재하는 클래스에 애너테이션 적용되도록 설정.
</beans>
2. main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
request.setCharacterEncoding("UTF-8");
%>
<html>
<head>
<meta charset=UTF-8">
<title>결과창</title>
</head>
<body>
<h1>안녕하세요!!</h1>
<h1>${msg} 페이지입니다!!</h1>
</body>
</html>
3. MainController.java
package com.spring.ex01; // 애너테이션이 적용되도록 하려면 해당 클래스가 반드시 Component-scan에서 설정한 패키지나 하위패키지에 존재해야함,
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller("maincontroller")
@RequestMapping("/test1")
public class MainController {
@RequestMapping(value="/main1.do", method=RequestMethod.GET)
public ModelAndView main1(HttpServletRequest request, HttpServletResponse response) throws Exception{
ModelAndView mav = new ModelAndView();
mav.addObject("msg", "main1");
mav.setViewName("main");
return mav;
}
@RequestMapping(value="/main2.do", method=RequestMethod.GET)
public ModelAndView main2(HttpServletRequest request, HttpServletResponse response) throws Exception{
ModelAndView mav = new ModelAndView();
mav.addObject("msg", "main2");
mav.setViewName("main");
return mav;
}
}
4. web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
</param-value>
</context-param>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>