Study Web Development

2월 24일

이전으로

Spring

2. 스프링 DI와 객체 관리

2-3 의존 관계 설정

Properties 타입
  1. 새 패키지 kr.spring.ch13 생성 후 새 클래스 BookClient 생성
package kr.spring.ch13;

import java.util.Properties;

public class BookClient {
	private Properties prop;

	public void setProp(Properties prop) {
		this.prop = prop;
	}

	@Override
	public String toString() {
		return "BookClient [prop=" + prop + "]";
	}
}
  1. applicationContext2.xml<beans> 태그 사이에 다음의 내용을 추가
	<!-- Properties 타입 프로퍼티 설정 -->
	<bean id="bookClient" class="kr.spring.ch13.BookClient">
		<property name="prop">
			<props> <!-- 다른 컬렉션 타입 태그들과 달리 타입명과 태그명이 불일치하므로 주의 -->
				<prop key="server">192.168.0.1</prop>
				<prop key="connectionTimeout">50000</prop>
			</props>
		</property>
	</bean>
  1. 새 클래스 SpringMain 생성
package kr.spring.ch13;

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

public class SpringMain {
	public static void main(String[] args) {
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext2.xml");

		// Properties 타입 프로퍼티 설정
		BookClient book = (BookClient)context.getBean("bookClient");
		System.out.println(book);
		
		context.close();	
	}
}
의존 관계 자동 설정
  1. 새 패키지 kr.spring.ch14 생성하고 새 클래스 WriteArticleDAO 생성
package kr.spring.ch14;

public class WriteArticleDAO {
	public void insert() {
		System.out.println("WriteArticleDAO의 insert() 메서드 실행");
	}
}
  1. 새 클래스 WriteArticleService 생성
package kr.spring.ch14;

public class WriteArticleService {
	private WriteArticleDAO writeArticleDAO;

	public void setWriteArticleDAO(WriteArticleDAO writeArticleDAO) {
		this.writeArticleDAO = writeArticleDAO;
	}
	
	public void write() {
		System.out.println("WriteArticleService의 write() 메서드 실행");
		writeArticleDAO.insert();
	}
}
  1. applicationContext3.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"
	xmlns:p="http://www.springframework.org/schema/p"
	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">

	<!-- 프로퍼티 이름을 이용한 의존 관계 자동 설정 -->
	<bean id="writeArticleService" class="kr.spring.ch14.WriteArticleService" autowire="byName"/> <!-- 해당 bean의 프로퍼티명과 일치하는 bean 식별자가 있으면 자동으로 설정됨  -->
	<bean id="writeArticleDAO" class="kr.spring.ch14.WriteArticleDAO"/>
</beans>
  1. 새 클래스 SpringMain 생성
package kr.spring.ch14;

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

public class SpringMain {
	public static void main(String[] args) {
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext3.xml");
		
		// 프로퍼티 이름을 이용한 의존 관계 자동 설정
		WriteArticleService articleService = (WriteArticleService)context.getBean("writeArticleService");
		articleService.write();
		
		context.close();
	}
}
  1. 새 패키지 kr.spring.ch15 생성 후 새 클래스 PhoneCallSystemMonitor 생성
package kr.spring.ch15;

public class SystemMonitor {
	private PhoneCall call;

	public void setCall(PhoneCall call) {
		this.call = call;
	}

	@Override
	public String toString() {
		return "SystemMonitor [call=" + call + "]";
	}
}
  1. applicationContext3.xml<beans> 태그 사이에 다음의 내용을 추가
	<!-- 프로퍼티 타입을 이용한 의존 관계 자동 설정 -->
	<bean id="systemMonitor" class="kr.spring.ch15.SystemMonitor" autowire="byType"/>
	<bean id="phoneCall1" class="kr.spring.ch15.PhoneCall"/>
	<!-- 동일한 타입의 객체가 존재할 경우 오류 발생 -->
	<!-- <bean id="phoneCall2" class="kr.spring.ch15.PhoneCall"/> -->
  1. 새 클래스 SpringMain 생성
package kr.spring.ch15;

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

public class SpringMain {
	public static void main(String[] args) {
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext3.xml");

		// 프로퍼티 타입을 이용한 의존 관계 자동 설정
		// 동일한 타입의 객체가 존재하면 오류 발생
		SystemMonitor monitor = (SystemMonitor)context.getBean("systemMonitor");
		System.out.println(monitor);
		
		context.close();		
	}
}

2-5 어노테이션 기반 설정

  1. 새 Spring Legacy Project 생성하여 프로젝트명을 ch02Annotation, 최상위 패키지명을 kr.spring.annotation로 지정하고 Spring MVC Project 선택
  2. pom.xml에서 <properties> 태그 내의 버전 변경
		<java-version>1.8</java-version>
		<org.springframework-version>5.0.20.RELEASE</org.springframework-version>
  1. Java Build Path와 Project Facets에서 버전을 1.8로 변경
  2. kr.spring.annotation 패키지 삭제
@Required
  1. 새 패키지 kr.spring.ch01 생성하고 새 클래스 Camera 생성
package kr.spring.ch01;

import org.springframework.beans.factory.annotation.Required;

public class Camera {
	private int number;
	
	// @Required 어노테이션을 이용한 필수 프로퍼티 검사
	// 메서드에만 명시 가능하고 프로퍼티에는 명시 불가능
	@Required
	public void setNumber(int number) {
		this.number = number;
	}

	@Override
	public String toString() {
		return "Camera [number=" + number + "]";
	}
}
  1. src/main/resourcesapplicationContext.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"
	xmlns:p="http://www.springframework.org/schema/p"
	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">

	<!-- 어노테이션 사용을 위해  아래 태그 추가 -->
	<context:annotation-config/>

	<!-- @Required 어노테이션을 이용한 필수 프로퍼티 설정 -->
	<bean id="camera1" class="kr.spring.ch01.Camera">
		<!-- number 프로퍼티에 @Required 어노테이션을 적용시 number 프로퍼티를 설정하지 않을 경우 예외 발생 -->
		<property name="number" value="1"/>
	</bean>
</beans>
  1. 새 클래스 SpringMain 생성
package kr.spring.ch01;

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

public class SpringMain {
	public static void main(String[] args) {
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		Camera camera = (Camera)context.getBean("camera1");
		System.out.println(camera);
		
		context.close();
	}
}
@Resource
  1. 새 패키지 kr.spring.ch02 생성하고 새 클래스 Camera 생성
package kr.spring.ch02;

public class Camera {
	private int number;
	
	public void setNumber(int number) {
		this.number = number;
	}

	@Override
	public String toString() {
		return "Camera [number=" + number + "]";
	}
}
  1. 새 클래스 HomeController 생성
package kr.spring.ch02;

import javax.annotation.Resource;

public class HomeController {
	// bean의 이름과 프로퍼티명이 일치하면 의존 관계 설정
	@Resource
	private Camera camera2;
	
	// @Resource(name="bean 객체의 식별자") : bean 객체의 식별자 지정
	@Resource(name="cameraz")
	private Camera camera3;
	
	private Camera camera4;

	public void setCamera2(Camera camera2) {
		this.camera2 = camera2;
	}
	
	public void setCamera3(Camera camera3) {
		this.camera3 = camera3;
	}
	
	@Resource
	public void setCamera4(Camera camera4) {
		this.camera4 = camera4;
	}

	@Override
	public String toString() {
		return "HomeController [camera2=" + camera2 + ", camera3=" + camera3 + ", camera4=" + camera4 + "]";
	}
}
  1. applicationContext.xml<beans> 태그 사이에 다음의 내용을 추가
	<!-- @Resource 어노테이션을 이용해서 bean 객체 이름과 프로퍼티명이 일치하면 의존 관계 주입  -->
	<bean id="homeController" class="kr.spring.ch02.HomeController"/>
	<bean id="camera2" class="kr.spring.ch02.Camera" p:number="2"/>
	<bean id="cameraz" class="kr.spring.ch02.Camera" p:number="3"/>
	<bean id="camera4" class="kr.spring.ch02.Camera" p:number="4"/>
  1. 새 클래스 SpringMain 생성
package kr.spring.ch02;

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

public class SpringMain {
	public static void main(String[] args) {
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

		// @Resource 어노테이션을 이용한 프로퍼티 설정
		HomeController home = (HomeController)context.getBean("homeController");
		System.out.println(home);
		
		context.close();
	}
}
@Autowired
  1. 새 패키지 kr.spring.ch03 생성하고 새 클래스 SmsSender, SystemMonitor 생성
package kr.spring.ch03;

import org.springframework.beans.factory.annotation.Autowired;

public class SystemMonitor {
	// 필드에 @Autowired를 지정
	// @Autowired
	private SmsSender sender;

	// 생성자에 @Autowired를 지정
	/*
	@Autowired
	public SystemMonitor(SmsSender sender) {
		this.sender = sender;
	}
	*/
	
	// 메서드에 @Autowired를 지정
	@Autowired
	public void setSender(SmsSender sender) {
		this.sender = sender;
	}

	@Override
	public String toString() {
		return "SystemMonitor [sender=" + sender + "]";
	}
}
  1. applicationContext.xml<beans> 태그 사이에 다음의 내용을 추가
	<!-- @Autowired 어노테이션을 이용한 의존 관계 자동 설정 -->
	<bean id="monitor" class="kr.spring.ch03.SystemMonitor"/>
	<bean id="smsSender" class="kr.spring.ch03.SmsSender"/>
  1. 새 클래스 SpringMain 생성
package kr.spring.ch03;

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

public class SpringMain {
	public static void main(String[] args) {
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

		// @Autowired 어노테이션을 이용한 의존 관계 자동 설정
		SystemMonitor monitor = (SystemMonitor)context.getBean("monitor");
		System.out.println(monitor);
		
		context.close();
	}
}
@Qualifier
  1. 새 패키지 kr.spring.ch04 생성하고 새 클래스 Recorder, SystemMonitor2 생성
package kr.spring.ch04;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class SystemMonitor2 {
	@Autowired
	// @Qualifier를 이용한 자동 설정 제한
	@Qualifier("main")
	private Recorder recorder;

	public void setRecorder(Recorder recorder) {
		this.recorder = recorder;
	}

	@Override
	public String toString() {
		return "SystemMonitor2 [recorder=" + recorder + "]";
	}
}
  1. applicationContext.xml<beans> 태그 사이에 다음의 내용을 추가
	<!-- @Qualifier 어노테이션을 이용한 자동 설정 제한 -->
	<bean id="systemMonitor" class="kr.spring.ch04.SystemMonitor2"/>
	<bean id="recorder1" class="kr.spring.ch04.Recorder">
		<qualifier value="main"/>
	</bean>
	<bean id="recorder2" class="kr.spring.ch04.Recorder"/>
  1. 새 클래스 SpringMain 생성
package kr.spring.ch04;

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

public class SpringMain {
	public static void main(String[] args) {
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

		SystemMonitor2 monitor = (SystemMonitor2)context.getBean("systemMonitor");
		System.out.println(monitor);
		
		context.close();
	}
}

2-6 어노테이션을 이용한 자동 스캔

  1. 새 패키지 kr.spring.ch05 생성
  2. src/main/resourcesapplicationContextScan.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"
	xmlns:p="http://www.springframework.org/schema/p"
	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">

	<!-- 
	컨테이너에 bean을 등록하기 위해서 패키지를 지정
	<context:component-scan/> 태그를 명시해서 자동 스캔할 패키지를 지정하면 <context:annotation-config/> 태그는 명시하지 않아도 어노테이션을 사용할 수 있음
	 -->
	<context:component-scan base-package="kr.spring.ch05"/>
</beans>
  1. 새 클래스 Camera 생성
package kr.spring.ch05;

import org.springframework.stereotype.Component;

// 자동 스캔 대상 지정
@Component
public class Camera {

}
  1. 새 클래스 HomeController 생성
package kr.spring.ch05;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/*
 * <context:component-scan/> 태그를 추가하면 Spring은 지정한 패키지에서 @Component 어노테이션이 적용된 클래스를 검색하여 bean으로 등록
 * 자동 등록된 bean의 id는 클래스 이름의 첫 글자를 소문자로 변경하여 부여됨
 * bean의 이름을 지정하고 싶으면 @Component("home")과 같이 명시하거나, 또는 @Component @Named("home")과 같이 명시함
 */
@Component
public class HomeController {
	@Autowired
	private Camera camera;

	public void setCamera(Camera camera) {
		this.camera = camera;
	}

	@Override
	public String toString() {
		return "HomeController [camera=" + camera + "]";
	}
}
  1. 새 클래스 SpringMain 생성
package kr.spring.ch05;

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

public class SpringMain {

	public static void main(String[] args) {
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContextScan.xml");

		// @Component 어노테이션을 이용한 bean 객체 생성
		HomeController home = (HomeController)context.getBean("homeController");
		System.out.println(home);
		
		context.close();
	}
}

2-7 자바 코드 기반 설정

  1. 새 패키지 kr.spring.ch06 생성하고 새 클래스 Worker 생성
package kr.spring.ch06;

public class Worker {
	public void work() {
		System.out.println("열심히 일하다.");
	}
}
  1. 새 클래스 Executer 생성
package kr.spring.ch06;

import org.springframework.beans.factory.annotation.Autowired;

public class Executer {
	@Autowired
	private Worker worker;

	public void setWorker(Worker worker) {
		this.worker = worker;
	}
	
	public void addUnit() {
		worker.work();
	}	
}
  1. 새 클래스 SpringConfig 생성
package kr.spring.ch06;

import javax.inject.Named;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// 자바 코드 기반 설정
@Configuration
public class SpringConfig {
	@Bean
	public Worker worker() {
		return new Worker();
	}
	
	/*
	 * 자바 코드 기반 설정에서는 bean 객체를 생성하는 메서드명이 bean의 식별자로 사용됨
	 * @Bean("식별자")처럼 @Bean 어노테이션에 bean의 식별자를 지정 가능
	 * @Named 어노테이션은 사용 불가
	 */
	@Bean
	public Executor executor2() {
		return new Executor();
	}
}
  1. 새 클래스 SpringMain 생성
package kr.spring.ch06;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

public class SpringMain {
	public static void main(String[] args) {
		// 자바 코드 기반 설정
		// 설정 정보를 가지고 있는 클래스를 읽어들여 컨테이너를 생성
		AbstractApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
		
		Executor executor = (Executor)context.getBean("executor2");
		executor.addUnit();
		
		context.close();
	}
}

3. 스프링 AOP

3-1 AOP 소개

3-1-1 AOP 용어
3-1-4 구현 가능한 Advice 종류

3-2 XML 스키마를 이용한 AOP 설정

  1. 새 Spring Legacy Project를 생성하여 프로젝트명을 ch03AOP, 최상위 패키지명을 kr.spring.AOP로 지정하고 Spring MVC Project 선택
  2. pom.xml에서 <properties> 태그 내의 버전 변경
		<java-version>1.8</java-version>
		<org.springframework-version>5.0.20.RELEASE</org.springframework-version>
  1. pom.xml에서 dependencies 태그 안에 다음의 내용을 추가
		<!-- 라이브러리 추가 시작 -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.8.9</version>
		</dependency>		
		<!-- 라이브러리 추가 끝 -->
  1. Java Build Path와 Project Facets에서 버전을 1.8로 변경
  2. kr.spring.AOP 패키지 삭제
  3. src/main/java 오른쪽 클릭하여 새 패키지 kr.spring.product 생성하고 새 클래스 Product 생성
package kr.spring.product;

public class Product {
	// 핵심 기능 수행
	public String launch() {
		System.out.println("launch() 메서드 출력");
		
		// 예외 발생시 호출되는 공통 기능을 테스트하기 위해
		// System.out.println(20/0);
		
		return "[상품 출시]";
	}
}
  1. 새 패키지 kr.spring.ch01 생성 후 새 클래스 MyFirstAdvice 생성
package kr.spring.ch01;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyFirstAdvice {
	// 공통 기능 수행
	public void before() {
		// 메서드 시작 직전에 동작하는 어드바이스
		System.out.println("Hello Before! **메서드가 호출되기 전에 나온다!");
	}
	
	public void afterReturning(String msg) {
		// 메서드 호출이 예외를 내보내지 않고 종료했을 때 동작하는 어드바이스
		System.out.println("Hello AfterReturning! **메서드가 호출한 후에 나온다! 전달된 객체 : " + msg);
	}
	
	public void afterThrowing(Throwable ex) {
		// 메서드 호출이 예외를 던졌을 때 동작하는 어드바이스
		System.out.println("Hello AfterThrowing! **예외가 생기면 나온다! 예외 : " + ex);
	}
	
	public void after() {
		// 예외가 발생해도 실행됨
		// 메서드 종료 후에 동작하는 어드바이스
		System.out.println("Hello After! **메서드가 호출된 후에 나온다!");
	}
	
	public String around(ProceedingJoinPoint joinpoint) throws Throwable {
		// 메서드 호출 전후에 동작하는 어드바이스
		System.out.println("Hello Around before! **메서드가 호출되기 전에 나온다!");
		String s = null;
		// try~catch~finally 구조로 명시해야 예외가 발생해도 메서드 실행 후 공통 기능을 수행함
		try {
			// 핵심 기능이 수행된 후 데이터 반환
			s = (String)joinpoint.proceed();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		finally {
			System.out.println("Hello Around after! **메서드가 호출된 후에 나온다! 반환된 객체 : " + s);
		}
		
		return s;
	}
}
  1. src/main/resourcesapplicationContext.xml 생성
    • aop 네임스페이스를 사용하고 라이브러리에 aspectjweaver가 있어야 함
<?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"
	xmlns:p="http://www.springframework.org/schema/p"
	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">

<!-- 
Aspect J의 Pointcut 표현식
execution(public void set*(..))
반환형이 void이고 메서드명이 set으로 시작하고, 인자가 0개 이상인 메서드 호출

execution(* kr.spring.ch01.*.*())
kr.spring.ch01 패키지의 인자가 없는 모든 메서드 호출

execution(* kr.spring.ch01..*.*(..))
kr.spring.ch01 패키지 및 하위 패키지에 있는 인자가 0개 이상인 메서드 호출

execution(Integer kr.spring.ch01..WriteArticleService.write(..))
반환형이 Integer이고, kr.spring.ch01 패키지 및 하위 패키지의 WriteArticleService 클래스에 있는 write() 메서드 호출

execution(* get*(*))
메서드명이 get으로 시작하고 인자가 1개인 메서드 호출

execution(* get*(*,*))
메서드명이 get으로 시작하고 인자가 2개인 메서드 호출

execution(* read*(Integer,..))
메서드명이 read로 시작하고 첫 번째 인자의 자료형이 Integer이며, 인자가 1개 이상인 메서드 호출
 -->

	<!-- 공통 기능이 구현된 클래스 -->
	<bean id="myFirstAdvice" class="kr.spring.ch01.MyFirstAdvice"/>
	
	<!-- 핵심 기능이 구현된 클래스 -->
	<bean id="product" class="kr.spring.product.Product"/>
	
	<!-- AOP 설정 -->
	<aop:config>
		<!-- Aspect 설정 : Advice를 어떤 Pointcut에 적용할지를 설정 -->
		<aop:aspect id="aspect" ref="myFirstAdvice"> <!-- 공통 기능이 있는 bean의 식별자를 등록 -->
			<!-- 실제로 Advice가 적용되는 지점 -->
			<aop:pointcut expression="execution(public String launch())" id="publicMethod"/>
			
			<!-- 실행할 공통 기능 메서드명과, 적용 대상인 Pointcut의 식별자를 등록 -->
			<!-- <aop:before method="before" pointcut-ref="publicMethod"/> -->
			
			<!-- 공통 기능 메서드의 인자명을 returning에 지정하면, 핵심 기능 반환 값이 해당 인자에 전달됨 -->
			<!-- <aop:after-returning method="afterReturning" pointcut-ref="publicMethod" returning="msg"/> -->
			
			<!-- 공통 기능 메서드의 인자명을 throwing에 지정하면, 핵심 기능에서 발생한 예외 객체가 해당 인자에 전달됨 -->
			<!-- <aop:after-throwing method="afterThrowing" pointcut-ref="publicMethod" throwing="ex"/> -->
			
			<!-- <aop:after method="after" pointcut-ref="publicMethod"/> -->
			
			<aop:around method="around" pointcut-ref="publicMethod"/>
		</aop:aspect>
	</aop:config>
</beans>
  1. kr.spring.ch01 패키지에 새 클래스 SpringMain 생성
package kr.spring.ch01;

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

import kr.spring.product.Product;

public class SpringMain {
	public static void main(String[] args) {
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		// 핵심 기능 실행, 설정 파일에 지정한 설정대로 공통 기능이 수행됨
		Product p = (Product)context.getBean("product");
		p.launch();
		
		context.close();
	}
}

다음으로