Spring
김영남
자바 개발 간소화
 종속객체 주입(DI: Dependency Injection)
 강한 결합을 제거하자
 AOP(Aspect Orientation Programming)
 횡단 관심사를 모듈화 하자
 Spring템플릿
 템플릿을 이용한 상투적인 코드 제거
종속객체 주입(DI: Dependency Injection)
 강한 결합을 제거하자
 원정을 떠나는 기사
강한 결합
Public class Knight {
private Quest quest;
public Knight() {
quest = RescueDamselQuest();  RescueDamselQuest에 강하게 결합된다.
}
}
종속객체 주입
Public class Knight {
private Quest quest;
public Knight(Quest quest) {
this.quest = quest;  Quest가 주입된다.
}
}
Knight
RescueDamsel
Quest
Knight
RescueDamsel
Quest
SlayDragon
Quest
종속객체 주입(DI: Dependency Injection)
 Spring의 XML설정을 이용한 종속객체 주입(wiring)
 Spring container가 객체(bean)를 관리한다.
<beans>
<bean id=“knight” class=“com.spring.knights.BraveKnight”>
<constructor-arg ref=“quest” />  “quest” bean 주입
</bean>
<bean id=“quest” class=“com.spring.knights.SlayDragonQuest” />  SlayDragonQuest 생성
</beans>
Spring container
Brave
Knight
SlayDragon
Quest
…
…
…
…
…
…
…
AOP(Aspect Oriented Programming)
 횡단 관심사를 모듈화 하자
 은행 전산 시스템
AOP(Aspect Oriented Programming)
 원정을 떠나는 기사와 응원하는 음유시인
public class BraveKnight {
private Quest quest;
private Minstrel minstrel;
public BraveKnight(Quest quest, Minstrel minstrel) {  기사에게 음유 시인을 주입해야 할까?
this.quest = quest;
this.minstrel = minstrel;
}
public void embarkOnQuest() {
minstrel.singBeforeQuest();  기사가 자체적인 음유 시인을 관리해야 할까?
quest.embark();
minstrel.singAfterQuest();
}
}
AOP(Aspect Oriented Programming)
 음유시인을 AOP로 선언하기
<beans>
<bean id=“knight” class=“com.spring.knights.BraveKnight”>
<constructor-arg ref=“quest” />
</bean>
<bean id=“quest” class=“com.spring.knights.SlayDragonQuest” />
<bean id=“minstrel” class=“com.spring.knights.Minstrel” />  음유시인 bean 선언
<aop:config>
<aop:aspect ref=“minstrel”>
<aop:pointcut id=“embark” expression=“execution(* *.embarkOnQuest(..))” />  pointcut정의
<aop:before pointcut-ref=“embark” method=“singBeforeQuest” />  before advice선언
<aop:after pointcut-ref=“embark” method=“singAfterQuest” />  after advice선언
</aop:aspect>
</aop:config>
</beans>
public class BraveKnight {
private Quest quest;
public BraveKnight(Quest quest)
this.quest = quest;
}
public void embarkOnQuest() {
quest.embark();
}
}
AOP(Aspect Oriented Programming)
 어드바이스(Advice)
 Aspect가 무엇을 해야하는지 정의
 조인포인트
 어드바이스를 끼워넣을 지점(point)
 포인트컷
 Aspect의 대상을 정의
 Aspect가 advice할 joinpoint영역을 좁힌다.
위치 특징
이전(before) 대상 메소드가 호출되기 전에 어드바이스 수행
이후(after) 결과에 상관없이 대상 메소드 완료 후 어드바이스 수행
반환 이후(after-returning) 대상 메소드가 성공적으로 완료된 후 어드바이스 수행
예외 발생 이후
(after-throwing)
대상 메소드가 예외를 던진 후 어드바이스 수행
주위(around) 대상 메소드 호출 전과 후에 어디바이스 수행
프록시
AOP(Aspect Oriented Programming)
 인트로덕션(Introduction)
 기존 클래스 변경없이 새 메소드나 멤버 변수 추가
 위빙(Weaving)
 타겟 객체에 새로운 프록시 객체를 생성
타겟
호출자
Spring 템플릿
 템플릿을 이용한 상투적인 코드 제거
public Employee getEmployeeById(long id) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection();
stmt = conn.prepareStatement(
“select id, firstname, lastname, salary from “ + employee where id=?”);  직원 조회
stmt.setLong(1, id);
rs = stmt.executeQuery();
Employee employee = null;
if (rs.next()) {
employee = new Employee();
employee.setId(rs.getLong(“id”));  데이터로부터 객체 생성
employee.setFirstName(rs.getString(“firstname”));
employee.setLastName(rs.getString(“lastname”));
employee.setSalary(rs.getBigDecimal(“salary”));
}
return employee;
} catch (SQLException e) {  여기서는 무엇을 수행해야 하지?
} finally {
if (rs != null) {  정리 작업
try {
rs.close();
} catch(SQLException e) {}
if (stmt != null) {
try {
stmt.close();
} catch(SQLEception e) {}
}
if (conn != null) {
try {
conn.close();
} catch(SQLException e) {}
}
}
return null;
}
Spring 템플릿
 템플릿을 이용한 상투적인 코드 제거
public Employee getEmployeeById(long id) {
return jdbcTemplate.queryForObject(
“select id, firstname, lastname, salary from “ + employee where id=?”  SQL쿼리
, new RowMapper<Employee>() {
public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {  결과를 객체에 매핑
employee = new Employee();
employee.setId(rs.getLong(“id”));
employee.setFirstName(rs.getString(“firstname”));
employee.setLastName(rs.getString(“lastname”));
employee.setSalary(rs.getBigDecimal(“salary”));
return employee;
}
}
, id);  쿼리 파라미터 지정
}

Spring

  • 1.
  • 2.
    자바 개발 간소화 종속객체 주입(DI: Dependency Injection)  강한 결합을 제거하자  AOP(Aspect Orientation Programming)  횡단 관심사를 모듈화 하자  Spring템플릿  템플릿을 이용한 상투적인 코드 제거
  • 3.
    종속객체 주입(DI: DependencyInjection)  강한 결합을 제거하자  원정을 떠나는 기사 강한 결합 Public class Knight { private Quest quest; public Knight() { quest = RescueDamselQuest();  RescueDamselQuest에 강하게 결합된다. } } 종속객체 주입 Public class Knight { private Quest quest; public Knight(Quest quest) { this.quest = quest;  Quest가 주입된다. } } Knight RescueDamsel Quest Knight RescueDamsel Quest SlayDragon Quest
  • 4.
    종속객체 주입(DI: DependencyInjection)  Spring의 XML설정을 이용한 종속객체 주입(wiring)  Spring container가 객체(bean)를 관리한다. <beans> <bean id=“knight” class=“com.spring.knights.BraveKnight”> <constructor-arg ref=“quest” />  “quest” bean 주입 </bean> <bean id=“quest” class=“com.spring.knights.SlayDragonQuest” />  SlayDragonQuest 생성 </beans> Spring container Brave Knight SlayDragon Quest … … … … … … …
  • 5.
    AOP(Aspect Oriented Programming) 횡단 관심사를 모듈화 하자  은행 전산 시스템
  • 6.
    AOP(Aspect Oriented Programming) 원정을 떠나는 기사와 응원하는 음유시인 public class BraveKnight { private Quest quest; private Minstrel minstrel; public BraveKnight(Quest quest, Minstrel minstrel) {  기사에게 음유 시인을 주입해야 할까? this.quest = quest; this.minstrel = minstrel; } public void embarkOnQuest() { minstrel.singBeforeQuest();  기사가 자체적인 음유 시인을 관리해야 할까? quest.embark(); minstrel.singAfterQuest(); } }
  • 7.
    AOP(Aspect Oriented Programming) 음유시인을 AOP로 선언하기 <beans> <bean id=“knight” class=“com.spring.knights.BraveKnight”> <constructor-arg ref=“quest” /> </bean> <bean id=“quest” class=“com.spring.knights.SlayDragonQuest” /> <bean id=“minstrel” class=“com.spring.knights.Minstrel” />  음유시인 bean 선언 <aop:config> <aop:aspect ref=“minstrel”> <aop:pointcut id=“embark” expression=“execution(* *.embarkOnQuest(..))” />  pointcut정의 <aop:before pointcut-ref=“embark” method=“singBeforeQuest” />  before advice선언 <aop:after pointcut-ref=“embark” method=“singAfterQuest” />  after advice선언 </aop:aspect> </aop:config> </beans> public class BraveKnight { private Quest quest; public BraveKnight(Quest quest) this.quest = quest; } public void embarkOnQuest() { quest.embark(); } }
  • 8.
    AOP(Aspect Oriented Programming) 어드바이스(Advice)  Aspect가 무엇을 해야하는지 정의  조인포인트  어드바이스를 끼워넣을 지점(point)  포인트컷  Aspect의 대상을 정의  Aspect가 advice할 joinpoint영역을 좁힌다. 위치 특징 이전(before) 대상 메소드가 호출되기 전에 어드바이스 수행 이후(after) 결과에 상관없이 대상 메소드 완료 후 어드바이스 수행 반환 이후(after-returning) 대상 메소드가 성공적으로 완료된 후 어드바이스 수행 예외 발생 이후 (after-throwing) 대상 메소드가 예외를 던진 후 어드바이스 수행 주위(around) 대상 메소드 호출 전과 후에 어디바이스 수행
  • 9.
    프록시 AOP(Aspect Oriented Programming) 인트로덕션(Introduction)  기존 클래스 변경없이 새 메소드나 멤버 변수 추가  위빙(Weaving)  타겟 객체에 새로운 프록시 객체를 생성 타겟 호출자
  • 10.
    Spring 템플릿  템플릿을이용한 상투적인 코드 제거 public Employee getEmployeeById(long id) { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = dataSource.getConnection(); stmt = conn.prepareStatement( “select id, firstname, lastname, salary from “ + employee where id=?”);  직원 조회 stmt.setLong(1, id); rs = stmt.executeQuery(); Employee employee = null; if (rs.next()) { employee = new Employee(); employee.setId(rs.getLong(“id”));  데이터로부터 객체 생성 employee.setFirstName(rs.getString(“firstname”)); employee.setLastName(rs.getString(“lastname”)); employee.setSalary(rs.getBigDecimal(“salary”)); } return employee; } catch (SQLException e) {  여기서는 무엇을 수행해야 하지? } finally { if (rs != null) {  정리 작업 try { rs.close(); } catch(SQLException e) {} if (stmt != null) { try { stmt.close(); } catch(SQLEception e) {} } if (conn != null) { try { conn.close(); } catch(SQLException e) {} } } return null; }
  • 11.
    Spring 템플릿  템플릿을이용한 상투적인 코드 제거 public Employee getEmployeeById(long id) { return jdbcTemplate.queryForObject( “select id, firstname, lastname, salary from “ + employee where id=?”  SQL쿼리 , new RowMapper<Employee>() { public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {  결과를 객체에 매핑 employee = new Employee(); employee.setId(rs.getLong(“id”)); employee.setFirstName(rs.getString(“firstname”)); employee.setLastName(rs.getString(“lastname”)); employee.setSalary(rs.getBigDecimal(“salary”)); return employee; } } , id);  쿼리 파라미터 지정 }