Chapter1. 스프링 속으로
1.1 자바 개발 간소화
1.1.1 POJO 의 힘
POJO: Plain Old Java Object. 어느 컨벤션이나 프레임워크의 요구사항이 전혀 없는 보통 자바 오브젝트
ex) extends, implements, annotations, ... 등을 제거한 오브젝트
- POJO 를 이용한 가볍고(lightwight) 비침투적(non-invasive)인 개발
1.1.2 종속객체 주입
DI: Dependency Injection. 구성요소간의 종속관계를 외부에서 주입하는 패턴
Setter, Interface, 그리고 Constructor based injection 을 흔히 볼 수 있다.
- DI와 인터페이스 지향(interface orientation)을 통한 느슨한 결합도(loose coupling)
1.1.3 애스펙트 적용
AOP: Aspect-Oriendted Programming. 비즈니스 로직에서 2차적 또는 보조 기능들을 분리시키는 개발 방법. 이렇게 분리시킨 모듈을 필요한 곳에 삽입하되, 코드 밖에서 설정한다.
로깅, 인증, 보안, 트랜잭션 관리, 메소드 성능검사, 예외반환, ... 같은 공동 모듈
- 애스펙트와 공통 규약을 통한 선언적(declarative) 프로그래밍
1.1.4 템플릿을 이용한 상투적인 코드 제거
- 애스펙트와 템플릿(template)을 통한 반복적인 코드 제거
1.2 빈을 담는 그릇, 컨테이너
- 스프링 기반 애플리케이션에서는 스프링 컨테이너(Spring Container) 안에서 객체가 태어나고, 자라고, 소멸한다.
- DI 을 이용해서 애플리케이션을 구성하는 컴포넌트를 관리.
- 크게 2가지로 분류된다.
- 빈 팩토리(BeanFactory)
- 애플리케이션 컨텍스트(Application Context)
1.2.1 또 하나의 컨테이너, 애플리케이션 컨텍스트
1.2.2 빈의 일생
1.3 스프링 현황
1.3.1 스프링 모듈
Core container
어플리케이션에서 빈의 생성, 설정 그리고 처리방법을 관리하는 컨테이너. 이 모듈 내에서 DI를 제공하는 스프링 빈 팩토리를 확인한다. 이 외에도 이메일, JNDI 액세스, EJB통합, 스케쥴링 등 다양한 엔터프라이즈 서비스도 제공한다. 모든 스프링 모듈은 코어 컨테이너 위에 구축되므로 암묵적으로 코어모듈을 사용한다.
Data Access/Integration
JDBC : spring-jdbc
데이터 access시 커넥션을 얻어오고, 질의객체를 생성하고 결과집합을 처리하고 커넥션을 닫는 작업을 반복한다. JDBC와 DAO 모듈은 이렇게 반복되는 코드를 추상화하고 리소스 관리를 해준다.
ORM : spring-orm
ORM모듈은 JDBC보다 객체관계 매핑 도구를 선호하는 사람들을 위한 모듈이다. 직접 ORM 솔루션 구현보다는 hibernate, java persistence, mybatis와 같은 ORM 프레임웍과의 연결고리를 제공해준다.
OXM : spring-oxm
객체 - XML 매핑
JMS : spring-jms
- Transaction : spring-tx
AOP모듈을 이용하여 객체들의 트랜젝션을 관리한다.
- web
- Web
- Web-MVC
- Web-Socket
- Web-Portlet
etc
- AOP
Aspects
AOP 모듈을 통해 aspect 지향 프로그래밍을 풍부하게 지원한다. AOP는 주로 애플리케이션의 전체 걸친 관심사 ( 트랜잭션, 보안, 로깅 etc)와 객체 간의 결합도를 낮추는데 이용된다.
Instrumentation
> JVM에 에이젼트를 추가하는 기능을 제공한다. 정확히는 톰캣용 위빙 에이젼트 제공. (좀더 찾아보자)
Messaging
Test
> 단위테스트를 위한 모의객체 구현이나 어플리케이션 컨텍스트에서 빈을 로드하고 이 컨텍스트에 있는 빈과의 작업을 지원한다.
1.3.2 스프링 포트폴리오
스프링 웹 플로
웹 어플리케이션의 네비게이션 흐름제어 구축을 지원합니다.
스프링 웹 서비스
SOAP 웹 서비스 개발을 용이하게 합니다.
- 스프링 시큐리티
포괄적이고 확장 가능한 인증 및 인가를 지원하여 애플리케이션을 보호합니다.
- 스프링 인티그레이션
엔터프라이즈 인티그레이션 패턴을 지원합니다.
- 스프링 배치
대량 배치작업에 대해 간결하고 최적화된 처리를 합니다.
- 스프링 데이터
데이터 접근에 대한 일관된 방식을 제공합니다. 관계형, 비관계형, 맵리듀스 등
- 스프링 소셜
페이스북, 트위터, 링크드인과 같은 서드파티 API와 쉽게 연결해줍니다.
- 스프링 모바일
장비 탐지 및 진보적인 랜더링 옵션을 통해 모바일 웹 어플리케이션 개발을 간편하게 합니다.
- 안드로이드 스프링
안드로이드 개발에 사용되는 스프링 컴포넌트를 제공합니다.
- 스프링 부트
스프링 애플리케이션을 구축하고 빠르게 실행 가능한 독단적인 뷰를 제공합니다.
Spring Framework Artifacts
GroupId | ArtifactId | Description |
---|---|---|
org.springframework | spring-aop | Proxy 기반 AOP 지원 |
org.springframework | spring-aspects | AspectJ 기반 스프링 aspect |
org.springframework | spring-beans | Bean 지원 |
org.springframework | spring-context | 애플리케이션 컨텍스트의 런타임 구현 , 스케쥴 지원 |
org.springframework | spring-context-support | 스프링과 서드파티 라이브러리간의 통합 지원 |
org.springframework | spring-core | Core 유틸리티 |
org.springframework | spring-expression | 스프링 표현 언어 (SpEL) |
org.springframework | spring-instrument | JVM 부트 스트래핑을 위한 instrumentation agent |
org.springframework | spring-instrument-tomcat | Instrumentation agent for Tomcat |
org.springframework | spring-jdbc | 데이터 소스 설정과 JDBC 액세스 지원하는 JDBC 패키지 |
org.springframework | spring-jms | 동기식 JMS 액세스와 메시지 리스너 컨테이너를 지원 |
org.springframework | spring-messaging | 메시징 아키텍쳐와 프로토콜 지원 |
org.springframework | spring-orm | JPA, hibernate 등의 ORM 지원 |
org.springframework | spring-oxm | Object/XML 매핑 |
org.springframework | spring-test | 유닛테스트 또는 integration 테스트 지원 |
org.springframework | spring-web | web 기능 지원 |
org.springframework | spring-webmvc | 웹 어플리케이션을 위한 REST웹 서비스 및 MVC 구현체 |
org.springframework | spring-webmvc-portlet | 포틀릿 환경의 MVC 구현체 |
org.springframework | spring-websocket | WebSocket, sockJS 구현체 (STOMP 지원) |
org.springframework.webflow | spring-webflow | 스프링 웹 플로워 |
org.springframework.ws | spring-ws-core | 스프링 웹 서비스 |
org.springframework.security | spring-security-web | 스프링 시큐리티 (spring aop) |
org.springframework.integration | spring-integration-core | 스프링 인티그레이션 |
org.springframework.batch | spring-batch-core | 스프링 배치 |
org.springframework.data | spring-data-releasetrain | 스프링 데이터 |
org.springframework.social | spring-social-facebook, spring-social-twitter | 스프링 소셜 |
org.springframework.mobile | spring-mobile-device | 스프링 모바일 |
org.springframework.android | spring-android-rest-template | 스프링 소셜 |
org.springframework.boot | spring-boot-starter-web | 스프링 부트 |
spring life cycle
spring 처리 흐름
1.4 스프링 새로운 기능
1.4.1 Spring 3.1
Cache Abstraction
- Cache enable
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> <cache:annotation-driven /> ... </beans>
- @Cacheable , @CacheEvict
@Cacheable("books") public Book findBook(ISBN isbn) {...} // use property 'rawNumber' on isbn argument as key @Cacheable(value="book", key="#isbn.rawNumber") public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) // cache only names shorter then 32 chars @Cacheable(value="book", condition="#name.length < 32") public Book findBook(String name) // evict all cache entries @CacheEvict(value = "books", allEntries=true) public void loadBooks(InputStream batch)
Bean Definition Profiles
@Configuration @Profile("production") public class JndiDataConfig { @Bean public DataSource dataSource() throws Exception { Context ctx = new InitialContext(); return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); } }
Environment Abstraction
datasource-config.xml
<beans profile="dev"> <jdbc:embedded-database id="dataSource"> <jdbc:script location="classpath:com/bank/config/sql/schema.sql"/> <jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/> </jdbc:embedded-database> </beans> <beans profile="production"> <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/> </beans>
- web.xml
<context-param> <param-name>spring.profiles.active</param-name> <param-value>production</param-value> </context-param>
- JVM option
-Dspring.profiles.active="production"
PropertySource Abstraction
<context:property-placeholder location="com/bank/config/datasource.properties"/> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClass" value="${database.driver}"/> <property name="jdbcUrl" value="${database.url}"/> <property name="username" value="${database.username}"/> <property name="password" value="${database.password}"/> </bean>
Code equivalents for Spring's XML namespaces
자주 사용하는 <context:component-scan/>, <tx:annotation-driven/>, <mvc:annotation-driven>의 스프링 XML 네임스페이스 엘리먼트와 동일한 기능을 대부분 @Enable 어노테이션의 형식으로 사용할 수 있다. 이 기능은 스프링 3.0에서 도입된 @Configuration 클래스와 결합해서 사용하도록 설계했다.
TestContext framework support for @Configuration classes and bean definition profiles
@ContextConfiguration 어노테이션은 이제 스프링 TestContext를 설정하는 @Configuration 클래스를 제공한다. 새로 추가된 @ActiveProfiles 어노테이션은 ApplicationContext 통합테스트에서 엑티브 빈 선언 프로파일을 선언적으로 설정을 지원한다.
c: namespace for more concise constructor injection
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="bar" class="x.y.Bar"/> <bean id="baz" class="x.y.Baz"/> <-- 'traditional' declaration --> <bean id="foo" class="x.y.Foo"> <constructor-arg ref="bar"/> <constructor-arg ref="baz"/> <constructor-arg value="[email protected]"/> </bean> <-- 'c-namespace' declaration --> <bean id="foo" class="x.y.Foo" c:bar-ref="bar" c:baz-ref="baz" c:email="[email protected]"> </beans>
Support for Servlet 3 code-based configuration of Servlet Container
- 전통적인 web.xml을 프로그래밍적으로 대체하는 서블릿 3.0의 ServletContainerInitializer에 기반을 둔 WebApplicationInitializer를 새로 추가했다
New HandlerMethod-based Support Classes For Annotated Controller Processing
- RequestMappingHandlerMapping <-- DefaultAnnotationHandlerMapping
- RequestMappingHandlerAdapter <-- AnnotationMethodHandlerAdapter
- ExceptionHandlerExceptionResolver <--- AnnotationMethodHandlerExceptionResolver
"consumes" and "produces" conditions in @RequestMapping
- 'Accept'헤더로 지정된 타입을 만드는 것(produce)과 마찬가지로 'Content-Type'헤더로 지정된 미디어타입을 메서드로 소비(consume)하는 것에 대한 지원이 개선
Flash Attributes and RedirectAttributes
- Support for injection against non-standard JavaBeans setters
- JPA EntityManagerFactory bootstrapping without persistence.xml
- Support for Servlet 3 MultipartResolver
- Support for Hibernate 4.x
- URI Template Variable Enhancements
- @RequestPart Annotation On Controller Method Arguments
- @Valid On @RequestBody Controller Method Arguments
- UriComponentsBuilder and UriComponents
- 3.1-release-notes 참고
1.4.2 Spring 3.2
- Support for Servlet 3 based asynchronous request processing
- Spring MVC Test framework
- Content negotiation improvements
@ControllerAdvice annotation
@ControllerAdvice public class GlobalExceptionController { @ExceptionHandler(CustomGenericException.class) public ModelAndView handleCustomException(CustomGenericException ex) { ModelAndView model = new ModelAndView("error/generic_error"); model.addObject("errCode", ex.getErrCode()); model.addObject("errMsg", ex.getErrMsg()); return model; } @ExceptionHandler(Exception.class) public ModelAndView handleAllException(Exception ex) { ModelAndView model = new ModelAndView("error/generic_error"); model.addObject("errMsg", "this is Exception.class"); return model; } }
Matrix variables
// GET /owners/42;q=11;r=12/pets/21;q=22;s=23 @RequestMapping(value = "/owners/{ownerId}/pets/{petId}") public void findPet( @MatrixVariable Map<String, String> matrixVars) { // matrixVars: ["q" : [11,22], "r" : 12, "s" : 23] }
Abstract base class for code-based Servlet 3+ container initialization
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return null; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[] { MyWebConfig.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } }
ResponseEntityExceptionHandler class
@ControllerAdvice public class ResthubExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler(value={ IllegalArgumentException.class, ValidationException.class, NotFoundException.class, NotImplementedException.class }) public ResponseEntity<Object> handleCustomException(Exception ex, WebRequest request) { HttpHeaders headers = new HttpHeaders(); HttpStatus status; if (ex instanceof IllegalArgumentException) { status = HttpStatus.BAD_REQUEST; } else if (ex instanceof ValidationException) { status = HttpStatus.BAD_REQUEST; } else if (ex instanceof NotFoundException) { status = HttpStatus.NOT_FOUND; } else if (ex instanceof NotImplementedException) { status = HttpStatus.NOT_IMPLEMENTED; } else { logger.warn("Unknown exception type: " + ex.getClass().getName()); status = HttpStatus.INTERNAL_SERVER_ERROR; return handleExceptionInternal(ex, null, headers, status, request); } return handleExceptionInternal(ex, buildRestError(ex, status), headers, status, request); } private RestError buildRestError(Exception ex, HttpStatus status) { RestError.Builder builder = new RestError.Builder(); builder.setCode(status.value()).setStatus(status.getReasonPhrase()).setThrowable(ex); return builder.build(); } }
- Support for generic types in the RestTemplate and in @RequestBody arguments
- Jackson JSON 2 and related improvements
- Tiles 3
- @RequestBody improvements
- HTTP PATCH method
- Excluded patterns in mapped interceptors
- Using meta-annotations for injection points and for bean definition methods
- Initial support for JCache 0.5
- Support for @DateTimeFormat without Joda Time & Global date & time formatting
- New Testing Features
- Concurrency refinements across the framework
- New Gradle-based build and move to GitHub
- Refined Java SE 7 / OpenJDK 7 support
- 3.2-release-notes 참고
1.4.3 Spring 4.0
- Improved Getting Started Experience
- Removed Deprecated Packages and Methods
- Java 8 (as well as 6 and 7) & Java EE 6 and 7
Groovy Bean Definition DSL
def reader = new GroovyBeanDefinitionReader(myApplicationContext) reader.beans { dataSource(BasicDataSource) { driverClassName = "org.hsqldb.jdbcDriver" url = "jdbc:hsqldb:mem:grailsDB" username = "sa" password = "" settings = [mynew:"setting"] } sessionFactory(SessionFactory) { dataSource = dataSource } myService(MyService) { nestedBean = { AnotherBean bean -> dataSource = dataSource } } }
- Core Container Improvements
- General Web Improvements
- WebSocket, SockJS, and STOMP Messaging
Testing Improvements
- Meta-Annotation Support for Testing
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) @ActiveProfiles("dev") @Transactional public @interface TransactionalDevTest { } @RunWith(SpringJUnit4ClassRunner.class) @TransactionalDevTest public class OrderRepositoryTests { }
- 4.0-release-notes 참고
1.5 Sample Project
$ git clone [email protected]:adel-yang/SpringStudy.git
$ gradle jettyRun
Access http://localhost:8080/