05. 스프링 AOP
AOP(Aspect Oriented Programming)
- 문제를 바라보는 관점을 기준으로 프로그래밍하는 기법
- 문제를 해결하기 위한 핵심 관심 사항과 전체에 적용되는 공통 관심 사항을 기준으로 프로그래밍 함으로써 공통 모듈을 여러 코드에 쉽게 적용
공통관심사항 (cross-cutting concern)
어플리케이션에서 로깅과 같은 기본적인 기능에서부터 트랙잭션이나 보안과 같은 기능에 이르기까지 어플리케이션 전반에걸쳐 적용되는 공통기능이
핵심로직을 핵심 관심 사항(core concern) 이라고 표현.
- 문제를 바라보는 관점을 기준으로 프로그래밍하는 기법
- 문제를 해결하기 위한 핵심 관심 사항과 전체에 적용되는 공통 관심 사항을 기준으로 프로그래밍 함으로써 공통 모듈을 여러 코드에 쉽게 적용
공통관심사항 (cross-cutting concern)
어플리케이션에서 로깅과 같은 기본적인 기능에서부터 트랙잭션이나 보안과 같은 기능에 이르기까지 어플리케이션 전반에걸쳐 적용되는 공통기능이
핵심로직을 핵심 관심 사항(core concern) 이라고 표현.
* AOP용어 *
Advice : 언제 공통 관심 기능을 핵심 로직에 적용할지를 정의
Joinpoint : Advice를 적용 가능한 지점을 의미 (메서드호출, 필드값 변경 등)
Pointcut : Joinpoint의 부분집합(그룹화) 실제로 Advice가 Joinpoint 적용된 스프링 정규표현식이나 AspectJ의 문법을 이용하여 Pointcut을 정의 할 수있다.
Weaving : Advice를 핵심 로직 코드에 적용하는것
Aspect : 공통관심사항
세가지 Weaving 방식
- 컴파일 시에 Weaving 하기
- 클래스 로딩시에 Weaving 하기
- 런타임 시에 Weaving 하기
Joinpoint : Advice를 적용 가능한 지점을 의미 (메서드호출, 필드값 변경 등)
Pointcut : Joinpoint의 부분집합(그룹화) 실제로 Advice가 Joinpoint 적용된 스프링 정규표현식이나 AspectJ의 문법을 이용하여 Pointcut을 정의 할 수있다.
Weaving : Advice를 핵심 로직 코드에 적용하는것
Aspect : 공통관심사항
세가지 Weaving 방식
- 컴파일 시에 Weaving 하기
- 클래스 로딩시에 Weaving 하기
- 런타임 시에 Weaving 하기
스프링에서의 AOP
스프링은 자체적으로 프록시 기반의 AOP를 지원한다 따라서 스프링 AOP는 메서드호출 Joinpoint만을 지원하고 필드값변경같은
Joinpoint를 사용하기 위해서는 AspectJ와 같이 풍부한 기능을 지원하느 AOP 도구를 사용
스프링은 세가지 방식으로 AOP구현
- XML 스키마 기반의 POJO클래스를 이용한 AOP 구현
- AspectJ 5/6에서 정의한 @Aspect 어노테이션 기반의 AOP구현
- 스프링 API를 이용한 AOP 구현 (많이사용하지는 않음)
스프링은 세가지 방식으로 AOP구현
- XML 스키마 기반의 POJO클래스를 이용한 AOP 구현
- AspectJ 5/6에서 정의한 @Aspect 어노테이션 기반의 AOP구현
- 스프링 API를 이용한 AOP 구현 (많이사용하지는 않음)
Advice : 언제 공통 관심 기능을 핵심 로직에 적용할지를 정의
Advice 정의 관련태그
<aop:before> : 메서드 실행전에 적용되는 Advice를 정의
<aop:after-returning> : 메서드가 정상적으로 실행된 후에 적용되는 Advice를 정의
<aop:throwing> : 예외를 발생시킬 때 적용되는 Advice를 정의 (catch와 비슷)
<aop:after> : 예외 여부와 상관없는 Advice를 정의한다 (finally 블록봐 비슷)
<aop:around> : 메서드 호출 이전, 이후, 예외 발생 등 모든 시점에서 적용 가능한 Advice를 정의한다.
<aop:before> : 메서드 실행전에 적용되는 Advice를 정의
<aop:after-returning> : 메서드가 정상적으로 실행된 후에 적용되는 Advice를 정의
<aop:throwing> : 예외를 발생시킬 때 적용되는 Advice를 정의 (catch와 비슷)
<aop:after> : 예외 여부와 상관없는 Advice를 정의한다 (finally 블록봐 비슷)
<aop:around> : 메서드 호출 이전, 이후, 예외 발생 등 모든 시점에서 적용 가능한 Advice를 정의한다.
public class ProfilingAdvice {
public Object trace(ProceedingJoinPoint joinPoint) throws Throwable{
전처리
try{
Object result = joinPoint.proceed();
return result;
}finally{
후처리
}
}
}
public Object trace(ProceedingJoinPoint joinPoint) throws Throwable{
전처리
String signatureString = joinPoint.getSignature().toShortString();
System.out.println(signatureString + "시작");
long start = System.currentTimeMillis();
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");
System.out.println(signatureString + "종료");
System.out.println(signatureString + "실행 시간 : " + (finish - start) + "ms");
}
}
}
XML스키마를 이용한 AOP 설정
<aop:config> : AOP 설정 정보임을 나타낸다.
<aop:aspect> : Aspect를 설정한다.
<aop:pointcut> : Pointcut을 설정 한다.
<aop:around> : Around Advice를 설정한다. 이외에도 다양한 Advice를 설정
<aop:config> : AOP 설정 정보임을 나타낸다.
<aop:aspect> : Aspect를 설정한다.
<aop:pointcut> : Pointcut을 설정 한다.
<aop:around> : Around Advice를 설정한다. 이외에도 다양한 Advice를 설정
Aspect : 공통관심사항
@Aspect 어노테이션을 이용해서 Aspect 클래스를 구현한다 .이때 Aspect 클래스는 Advice를 구현한 메서드와 Pointcut을 포함한다.
Pointcut : Joinpoint의 부분집합(그룹화) 실제로 Advice가 Joinpoint 적용된 스프링 정규표현식이나 AspectJ의 문법을 이용하여 Pointcut을 정의 할 수있다.
Joinpoint : Advice를 적용 가능한 지점을 의미 (메서드호출, 필드값 변경 등)
Weaving : Advice를 핵심 로직 코드에 적용하는것
AspectJ의 Pointcut 표현식 P181
===============================프로젝트===================================
예제.
src/
madvirus.spring.chap05.aop.annot
ProfilingAspect (어노테이션)
madvirus.spring.chap05.aop.pojo
Main (POJO)
ProfilingAdvice (POJO)
madvirus.spring.chap05.board
Article ()
madvirus.spring.chap05.board.dao
ArticleDao (interface)
MySQLArticleDao ()
madvirus.spring.chap05.board.service
WriteArticleService (interface)
WriteArticleServiceImpl ()
madvirus.spring.chap05.member
Member ()
madvirus.spring.chap05.member.service
MemberService (interface)
MemberServiceImpl ()
UpdateInfo ()
applicationContext.xml (POJO)
applicationContext02.xml (어노테이션)
==================================코드======================================
예제.
src/
madvirus.spring.chap05.aop.annot
Main02(어노테이션)
package madvirus.spring.chap05.aop.annot;
import madvirus.spring.chap05.board.Article;
import madvirus.spring.chap05.board.service.WriteArticleService;
import madvirus.spring.chap05.member.Member;
import madvirus.spring.chap05.member.service.MemberService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main02 {
public static void main(String[] args){
String[] configLocations = new String[] {"applicationContext02.xml" };
ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
WriteArticleService articaleService = (WriteArticleService)context.getBean("writeArticleService");
articaleService.write(new Article());
}
}
import madvirus.spring.chap05.board.Article;
import madvirus.spring.chap05.board.service.WriteArticleService;
import madvirus.spring.chap05.member.Member;
import madvirus.spring.chap05.member.service.MemberService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main02 {
public static void main(String[] args){
String[] configLocations = new String[] {"applicationContext02.xml" };
ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
WriteArticleService articaleService = (WriteArticleService)context.getBean("writeArticleService");
articaleService.write(new Article());
}
}
ProfilingAspect (어노테이션)
package madvirus.spring.chap05.aop.annot;
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 * madvirus.spring.chap05.board..*(..))")
private void profileTarget(){}
@Around("profileTarget()")
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");
}
}
}
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 * madvirus.spring.chap05.board..*(..))")
private void profileTarget(){}
@Around("profileTarget()")
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");
}
}
}
madvirus.spring.chap05.aop.pojo
Main (POJO)
package madvirus.spring.chap05.aop.pojo;
import madvirus.spring.chap05.board.Article;
import madvirus.spring.chap05.board.service.WriteArticleService;
import madvirus.spring.chap05.member.Member;
import madvirus.spring.chap05.member.service.MemberService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args){
String[] configLocations = new String[] {"applicationContext.xml" };
ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
WriteArticleService articaleService = (WriteArticleService)context.getBean("writeArticleService");
articaleService.write(new Article());
MemberService memberService = (MemberService)context.getBean("memberService");
memberService.regist(new Member());
}
}
import madvirus.spring.chap05.board.Article;
import madvirus.spring.chap05.board.service.WriteArticleService;
import madvirus.spring.chap05.member.Member;
import madvirus.spring.chap05.member.service.MemberService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args){
String[] configLocations = new String[] {"applicationContext.xml" };
ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
WriteArticleService articaleService = (WriteArticleService)context.getBean("writeArticleService");
articaleService.write(new Article());
MemberService memberService = (MemberService)context.getBean("memberService");
memberService.regist(new Member());
}
}
ProfilingAdvice (POJO)
package madvirus.spring.chap05.aop.pojo;
import org.aspectj.lang.ProceedingJoinPoint;
public class ProfilingAdvice {
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");
}
}
}
import org.aspectj.lang.ProceedingJoinPoint;
public class ProfilingAdvice {
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");
}
}
}
madvirus.spring.chap05.board
Article ()
package madvirus.spring.chap05.board;
import madvirus.spring.chap05.board.dao.ArticleDao;
import org.springframework.beans.factory.annotation.Configurable;
public class Article {
private int id;
private ArticleDao articleDao;
public Article() {
}
public Article(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void increaseReadCount() {
articleDao.updateReadCount(id, 1);
}
public void setArticleDao(ArticleDao articleDao) {
this.articleDao = articleDao;
}
}
import madvirus.spring.chap05.board.dao.ArticleDao;
import org.springframework.beans.factory.annotation.Configurable;
public class Article {
private int id;
private ArticleDao articleDao;
public Article() {
}
public Article(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void increaseReadCount() {
articleDao.updateReadCount(id, 1);
}
public void setArticleDao(ArticleDao articleDao) {
this.articleDao = articleDao;
}
}
madvirus.spring.chap05.board.dao
ArticleDao (interface)
package madvirus.spring.chap05.board.dao;
import madvirus.spring.chap05.board.Article;
public interface ArticleDao {
void insert(Article article);
void updateReadCount(int id, int i);
}
import madvirus.spring.chap05.board.Article;
public interface ArticleDao {
void insert(Article article);
void updateReadCount(int id, int i);
}
MySQLArticleDao ()
package madvirus.spring.chap05.board.dao;
import madvirus.spring.chap05.board.Article;
public class MySQLArticleDao implements ArticleDao {
@Override
public void insert(Article article) {
System.out.println("MySQLArticleDao.insert() 실행");
}
@Override
public void updateReadCount(int articleId, int inc) {
System.out.println("MySQLArticleDao.updateReadCount() 실행");
}
}
import madvirus.spring.chap05.board.Article;
public class MySQLArticleDao implements ArticleDao {
@Override
public void insert(Article article) {
System.out.println("MySQLArticleDao.insert() 실행");
}
@Override
public void updateReadCount(int articleId, int inc) {
System.out.println("MySQLArticleDao.updateReadCount() 실행");
}
}
madvirus.spring.chap05.board.service
WriteArticleService (interface)
package madvirus.spring.chap05.board.service;
import madvirus.spring.chap05.board.Article;
public interface WriteArticleService {
void write(Article article);
}
import madvirus.spring.chap05.board.Article;
public interface WriteArticleService {
void write(Article article);
}
WriteArticleServiceImpl ()
package madvirus.spring.chap05.board.service;
import madvirus.spring.chap05.board.Article;
import madvirus.spring.chap05.board.dao.ArticleDao;
public class WriteArticleServiceImpl implements WriteArticleService {
private ArticleDao articleDao;
public WriteArticleServiceImpl() {
}
public WriteArticleServiceImpl(ArticleDao articleDao) {
this.articleDao = articleDao;
}
//실제적으로 출력될 메서드
@Override
public void write(Article article) {
System.out.println("WriteArticleServiceImpl.write() 메서드 실행");
articleDao.insert(article);
}
}
import madvirus.spring.chap05.board.Article;
import madvirus.spring.chap05.board.dao.ArticleDao;
public class WriteArticleServiceImpl implements WriteArticleService {
private ArticleDao articleDao;
public WriteArticleServiceImpl() {
}
public WriteArticleServiceImpl(ArticleDao articleDao) {
this.articleDao = articleDao;
}
//실제적으로 출력될 메서드
@Override
public void write(Article article) {
System.out.println("WriteArticleServiceImpl.write() 메서드 실행");
articleDao.insert(article);
}
}
madvirus.spring.chap05.member
Member ()
package madvirus.spring.chap05.member;
public class Member {
}
public class Member {
}
madvirus.spring.chap05.member.service
MemberService (interface)
package madvirus.spring.chap05.member.service;
import madvirus.spring.chap05.member.Member;
public interface MemberService {
void regist(Member member);
boolean update(String memberId,UpdateInfo info);
}
import madvirus.spring.chap05.member.Member;
public interface MemberService {
void regist(Member member);
boolean update(String memberId,UpdateInfo info);
}
MemberServiceImpl ()
package madvirus.spring.chap05.member.service;
import madvirus.spring.chap05.member.Member;
public class MemberServiceImpl implements MemberService {
@Override
public void regist(Member member) {
System.out.println("MemberServiceImpl.regist() 메서드 실행");
}
@Override
public boolean update(String memberId, UpdateInfo info) {
System.out.println("MemberServiceImpl.update() 메서드 실행");
return true;
}
}
import madvirus.spring.chap05.member.Member;
public class MemberServiceImpl implements MemberService {
@Override
public void regist(Member member) {
System.out.println("MemberServiceImpl.regist() 메서드 실행");
}
@Override
public boolean update(String memberId, UpdateInfo info) {
System.out.println("MemberServiceImpl.update() 메서드 실행");
return true;
}
}
UpdateInfo ()
package madvirus.spring.chap05.member.service;
public class UpdateInfo {
}
public class UpdateInfo {
}
applicationContext.xml (POJO)
<?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">
<!-- Advice 클래스를 빈으로 등록 -->
<bean id="preformanceTraceAdvice" class="madvirus.spring.chap05.aop.pojo.ProfilingAdvice"/>
<!-- Aspect 설정 : Advice를 어떤 Pointcut에 적용할 지 설정 -->
<aop:config>
<aop:aspect id="traceAspect1" ref="preformanceTraceAdvice">
<!-- 광범위하게 적용 : madvirus.spring.chap05.board 안에있는 모든 메소드에 적용 -->
<aop:pointcut id="publicMethod" expression="execution(public * madvirus.spring.chap05.board..*(..))" />
<aop:around pointcut-ref="publicMethod" method="trace"/>
</aop:aspect>
<aop:aspect id="traceAspect2" ref="preformanceTraceAdvice">
<!-- 광범위하게 적용 : madvirus.spring.chap05.board 안에있는 모든 메소드에 적용 -->
<aop:around pointcut="execution(public * madvirus.spring.chap05.member..*(..))" method="trace"/>
</aop:aspect>
</aop:config>
<bean id="writeArticleService" class="madvirus.spring.chap05.board.service.WriteArticleServiceImpl">
<constructor-arg>
<ref bean="articleDao"/>
</constructor-arg>
</bean>
<bean id="articleDao" class="madvirus.spring.chap05.board.dao.MySQLArticleDao" />
<bean id="memberService" class="madvirus.spring.chap05.member.service.MemberServiceImpl"/>
</beans>
<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">
<!-- Advice 클래스를 빈으로 등록 -->
<bean id="preformanceTraceAdvice" class="madvirus.spring.chap05.aop.pojo.ProfilingAdvice"/>
<!-- Aspect 설정 : Advice를 어떤 Pointcut에 적용할 지 설정 -->
<aop:config>
<aop:aspect id="traceAspect1" ref="preformanceTraceAdvice">
<!-- 광범위하게 적용 : madvirus.spring.chap05.board 안에있는 모든 메소드에 적용 -->
<aop:pointcut id="publicMethod" expression="execution(public * madvirus.spring.chap05.board..*(..))" />
<aop:around pointcut-ref="publicMethod" method="trace"/>
</aop:aspect>
<aop:aspect id="traceAspect2" ref="preformanceTraceAdvice">
<!-- 광범위하게 적용 : madvirus.spring.chap05.board 안에있는 모든 메소드에 적용 -->
<aop:around pointcut="execution(public * madvirus.spring.chap05.member..*(..))" method="trace"/>
</aop:aspect>
</aop:config>
<bean id="writeArticleService" class="madvirus.spring.chap05.board.service.WriteArticleServiceImpl">
<constructor-arg>
<ref bean="articleDao"/>
</constructor-arg>
</bean>
<bean id="articleDao" class="madvirus.spring.chap05.board.dao.MySQLArticleDao" />
<bean id="memberService" class="madvirus.spring.chap05.member.service.MemberServiceImpl"/>
</beans>
applicationContext02.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">
<aop:aspectj-autoproxy/>
<!-- Advice 클래스를 빈으로 등록 -->
<bean id="preformanceTraceAspect" class="madvirus.spring.chap05.aop.annot.ProfilingAspect"/>
<bean id="writeArticleService" class="madvirus.spring.chap05.board.service.WriteArticleServiceImpl">
<constructor-arg>
<ref bean="articleDao"/>
</constructor-arg>
</bean>
<bean id="articleDao" class="madvirus.spring.chap05.board.dao.MySQLArticleDao" />
</beans>
<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">
<aop:aspectj-autoproxy/>
<!-- Advice 클래스를 빈으로 등록 -->
<bean id="preformanceTraceAspect" class="madvirus.spring.chap05.aop.annot.ProfilingAspect"/>
<bean id="writeArticleService" class="madvirus.spring.chap05.board.service.WriteArticleServiceImpl">
<constructor-arg>
<ref bean="articleDao"/>
</constructor-arg>
</bean>
<bean id="articleDao" class="madvirus.spring.chap05.board.dao.MySQLArticleDao" />
</beans>
==================================결과값=====================================
1. (POJO)
2. (POJO)
3 (어노테이션)
'스프링3.0' 카테고리의 다른 글
Spring3.0 View error filedown (0) | 2012.05.14 |
---|---|
Spring3.0 MVC 웹요청 처리 (0) | 2012.05.14 |
Spring3.0 DI 3 (0) | 2012.05.14 |
스프링 3.0 @ 어노테이션 기반 설정 (0) | 2012.05.14 |
Spring3.0 message&event (1) | 2012.05.14 |