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 + "]";
}
}
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>
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();
}
}
<bean>
태그의 autowire
속성에 값을 지정하면 bean 객체의 타입이나 이름을 이용하여 의존 객체를 자동으로 설정할 수 있음autowire="byName"
autowire="byType"
autowire="constructor"
kr.spring.ch14
생성하고 새 클래스 WriteArticleDAO
생성package kr.spring.ch14;
public class WriteArticleDAO {
public void insert() {
System.out.println("WriteArticleDAO의 insert() 메서드 실행");
}
}
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();
}
}
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>
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();
}
}
kr.spring.ch15
생성 후 새 클래스 PhoneCall
과 SystemMonitor
생성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 + "]";
}
}
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"/> -->
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();
}
}
ch02Annotation
, 최상위 패키지명을 kr.spring.annotation
로 지정하고 Spring MVC Project 선택pom.xml
에서 <properties>
태그 내의 버전 변경 <java-version>1.8</java-version>
<org.springframework-version>5.0.20.RELEASE</org.springframework-version>
kr.spring.annotation
패키지 삭제@Required
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 + "]";
}
}
src/main/resources
에 applicationContext.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>
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
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 + "]";
}
}
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 + "]";
}
}
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"/>
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
@Autowired
어노테이션이 적용된 bean 객체를 생성할 때 예외를 발생@Autowired(required=false)
로 지정하면 해당 타입의 bean 객체가 존재하지 않더라도 Spring이 예외를 발생하지 않음(기본값은 true
)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 + "]";
}
}
applicationContext.xml
의 <beans>
태그 사이에 다음의 내용을 추가 <!-- @Autowired 어노테이션을 이용한 의존 관계 자동 설정 -->
<bean id="monitor" class="kr.spring.ch03.SystemMonitor"/>
<bean id="smsSender" class="kr.spring.ch03.SmsSender"/>
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
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 + "]";
}
}
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"/>
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();
}
}
.xml
설정 파일에 bean을 직접 등록하지 않고, <context:component-scan/>
으로 스캔 대상 패키지만 명시 후 어노테이션으로 처리하는 방식을 사용kr.spring.ch05
생성src/main/resources
에 applicationContextScan.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>
Camera
생성package kr.spring.ch05;
import org.springframework.stereotype.Component;
// 자동 스캔 대상 지정
@Component
public class Camera {
}
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 + "]";
}
}
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();
}
}
.xml
설정 파일을 사용하지 않고, 어노테이션을 이용해 자바 코드 기반으로 컨테이너 설정 가능kr.spring.ch06
생성하고 새 클래스 Worker
생성package kr.spring.ch06;
public class Worker {
public void work() {
System.out.println("열심히 일하다.");
}
}
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();
}
}
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();
}
}
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();
}
}
ch03AOP
, 최상위 패키지명을 kr.spring.AOP
로 지정하고 Spring MVC Project 선택pom.xml
에서 <properties>
태그 내의 버전 변경 <java-version>1.8</java-version>
<org.springframework-version>5.0.20.RELEASE</org.springframework-version>
pom.xml
에서 dependencies
태그 안에 다음의 내용을 추가 <!-- 라이브러리 추가 시작 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<!-- 라이브러리 추가 끝 -->
kr.spring.AOP
패키지 삭제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 "[상품 출시]";
}
}
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;
}
}
src/main/resources
에 applicationContext.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">
<!--
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>
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();
}
}