5. 5 | GEEK ACADEMY 2013
Introduction to Spring
• What's Spring
• Dependency Injection
• Module of Spring
• Usage scenarios
6. 6 | GEEK ACADEMY 2013
What's Spring
• Goals
– make Enterprise Java easier to use
– promote good programming practice
– enabling a POJO-based programming model that is applicable in
a wide range of environments
• Some said Spring is just a “glue” for connecting all state of the art
technologies together (a.k.a Integration Framework) via it’s Application
Context.
• Heart and Soul of Spring is Dependency Injection and Aspect Oriented
Programming.
7. 7 | GEEK ACADEMY 2013
What is Spring Framework today?
• an open source application framework
• a lightweight solution for enterprise applications
• non-invasive (POJO based)
• is modular
• extendible for other frameworks
• de facto standard of Java Enterprise Application
8. 8 | GEEK ACADEMY 2013
Dependency Injection/Inversion of Control
9. 9 | GEEK ACADEMY 2013
Dependency Injection/Inversion of Control
• ทั่วไป • DI
Hollywood Principle: "Don't call me, I'll call you."
18. 18 | GEEK ACADEMY 2013
Basic bean
• What is bean?
• Creating bean
• Bean scope
• IoC Container
• Additional Features
• Bean Life cycle
19. 19 | GEEK ACADEMY 2013
What is bean?
• The objects that form the backbone of your application and that
are managed by the Spring IoC container are called beans.
• A bean is an object that is instantiated, assembled, and
otherwise managed by a Spring IoC container.
• These beans are created with the configuration metadata that
you supply to the container, for example, in the form of XML
<bean/> definitions which you have already seen in previous
chapters.
20. 20 | GEEK ACADEMY 2013
Creating bean
• Declaring a simple bean.
<bean id="hello" class="mypackage.HelloWorld" />
HelloWorld hello = new mypackage.HelloWorld();
21. 21 | GEEK ACADEMY 2013
Creating bean
• Injecting through constructors.
<bean id="hello" class="mypackage.HelloWorld">
<constructor-arg value="Hello World" />
</bean>
HelloWorld hello = new mypackage.HelloWorld(“Hello World”);
22. 22 | GEEK ACADEMY 2013
Creating bean
• Creating bean form factory.
<bean id="md5Digest"
class="java.security.MessageDigest"
factory-method="getInstance">
<constructor-arg value="MD5"/>
</bean>
MessageDigest md5Digest = new java.security.MessageDigest
.getInstance(“MD5”);
23. 23 | GEEK ACADEMY 2013
Injecting into bean properties
• Injecting simple values.
<bean id="hello" class="mypackage.HelloWorld">
<property name=”message” value="Hello World" />
</bean>
HelloWorld hello = new mypackage.HelloWorld();
hello.setMessage(“Hello World”);
24. 24 | GEEK ACADEMY 2013
Injecting into bean properties
• References to other beans (collaborators).
<bean id="msgService" class="mypackage.MessageService">
<property name=”messageProvider” ref="hello" />
</bean>
HelloWorld hello = …
MessageService msgService = new
mypackage.MessageService();
msgService.setMessageProvider(hello);
25. 25 | GEEK ACADEMY 2013
Injecting into bean properties
• Inner beans
<bean id="outer" class="...">
<!-- instead of using a reference to a target bean, simply
define the target bean inline -->
<property name="target">
<!-- this is the inner bean -->
<bean class="com.mycompany.Person">
<property name="name" value="Fiona Apple"/>
<property name="age" value="25"/>
</bean>
</property>
</bean>
33. 33 | GEEK ACADEMY 2013
Bean Scope
• Other scopes
– request, session, and global session are only used in
web-based applications.
• Custom scopes – Spring Framework Reference
39. 39 | GEEK ACADEMY 2013
Container Overview
• Essence of IoC container
40. 40 | GEEK ACADEMY 2013
Configuration metadata
• XML-based configuration metadata
• Annotation-based configuration metadata (v2.5)
– Java-based configuration (3.0) provided by Spring
JavaConfig project
41. 41 | GEEK ACADEMY 2013
Configuration metadata
• XML-based configuration
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
42. 42 | GEEK ACADEMY 2013
Configuration metadata
• Java-based configuration (v3.0)
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
<beans>
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
43. 43 | GEEK ACADEMY 2013
Instantiating a container
• ApplicationContext represents the Spring IoC container
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
ApplicationContext ctx =
new AnnotationConfigApplicationContext(MyService.class, Dependency1.class, Dependency2.class);
GenericXmlApplicationContext context = new GenericXmlApplicationContext();
context.getEnvironment().setActiveProfiles("production", "no-jms");
context.load("spring-master.xml");
context.refresh();
44. 44 | GEEK ACADEMY 2013
Using the container
// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);
// use configured instance
List userList = service.getUsernameList();
50. 50 | GEEK ACADEMY 2013
Using depends-on
• Bean dependency
– one bean is set as a property of another
– accomplish this with the <ref/> element in XML-based
configuration metadata
– sometimes dependencies between beans are less direct
• For example, a static initializer in a class needs to be
triggered, such as database driver registration.
52. 52 | GEEK ACADEMY 2013
Lazy-initialized beans
• IoC container create a bean instance when it is first requested
<bean id="lazy" class="ExpensiveToCreateBean" lazy-init="true"/>
59. 59 | GEEK ACADEMY 2013
Lifecycle Callback
• Implement Interface
– InitializingBean.afterPropertiesSet()
– DisposableBean.destroy()
• <bean/> element
– Init-method attribute
– destroy-method attribute
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
@PostConstruct
@PreDestroy
Internally, the Spring Framework uses BeanPostProcessor implementations
to process any callback interfaces it can find and call the appropriate methods.
60. 60 | GEEK ACADEMY 2013
Bean Aware
• Spring offers a range of Aware interfaces that
allow beans to indicate to the container that they
require a certain infrastructure dependency.
– ApplicationContextAware - Declaring ApplicationContext
– BeanFactoryAware - Declaring BeanFactory
– BeanNameAware - Name of the declaring bean
– ResourceLoaderAware - Configured loader for low-level access to resources
– ServletConfigAware - Current ServletConfig the container runs in. Valid only in a
web-aware Spring ApplicationContext
– ServletContextAware - Current ServletContext the container runs in. Valid only
in a web-aware Spring ApplicationContext
– Etc.
61. 61 | GEEK ACADEMY 2013
Customizing instantiation logic with a FactoryBean
• FactoryBean interface is a point of pluggability into the Spring
IoC container's instantiation logic for complex initialization
bean.
public interface FactoryBean<T> {
/** Return an instance of the object managed by this factory. */
T getObject() throws Exception;
/** Return the type of object that this FactoryBean creates. */
Class<?> getObjectType();
/** Is the object managed by this factory a singleton? */
boolean isSingleton();
}
<bean id="bean" class="MyFactoryBean"/>
63. 63 | GEEK ACADEMY 2013
Container Extension Points
• Becareful
– Note also that BeanPostProcessors registered programmatically are always processed before
those registered through auto-detection, regardless of any explicit ordering.
– Note that if you have beans wired into your BeanPostProcessor using autowiring or @Resource
(which may fall back to autowiring), Spring might access unexpected beans when searching for
type-matching dependency candidates, and therefore make them ineligible for auto-proxying or other
kinds of bean post-processing. For example, if you have a dependency annotated with @Resource where
the field/setter name does not directly correspond to the declared name of a bean and no name attribute
is used, then Spring will access other beans for matching them by type.
• This means that if you have @Transactional in a bean that is loaded in reference to a
BeanPostProcessor, that annotation is effectively ignored.
• The solution generally would be that if you need transactional behavior in a bean that has to
be loaded in reference to a BeanPostProcessor, you would need to use non-AOP transaction
definitions - i.e. use TransactionTemplate.
• Container Extension Points – Spring Framework Reference
70. 70 | GEEK ACADEMY 2013
@Value
@Component("ejbAccessService")
public class EjbAccessService {
/** The provider api connection url. */
@Value("${provider.api.url}")
private String apiUrl;
/** The provider api connection username. */
@Value("${provider.api.username}")
private String apiUsername;
/** The provider api connection password. */
@Value("${provider.api.password}")
private String apiPassword;
...
}
provider.api.url=corbaloc:iiop:localhost:2809
provider.api.username=Administrator
provider.api.password=password
<context:property-placeholder
location="classpath:META-INF/provider.properties"
properties-ref="providerProps" />
<util:properties id="providerProps">
<prop key="provider.api.url">t3://127.0.0.1:7001</prop>
<prop key="provider.api.username">weblogic</prop>
<prop key="provider.api.password">weblogic</prop>
</util:properties>
Properties
placeholders
71. 71 | GEEK ACADEMY 2013
@Autowired (1)
@Service("accountService")
public class AccountServiceImpl {
@Autowired
private AccountRepository repository;
@Autowired
public AccountServiceImpl(AccountRepository repository) {}
@Autowired(required = false)
public void setRepository(AccountRepository repository) {}
@Autowired
public void populate(Repository r, OrderService s) {}
...
}
Matches by Type → Restricts by Qualifiers → Matches by Name
72. 72 | GEEK ACADEMY 2013
@Autowired (2)
@Service
public class AccountServiceImpl {
@Autowired
private AccountRepository[] repositories;
@Autowired
public AccountServiceImpl(Set<AccountRepository> set) {}
@Autowired(required = false)
public void setRepositories(Map<String,AccountRepository> map){}
...
}
73. 73 | GEEK ACADEMY 2013
@Required
public class AccountServiceImpl {
private AccountRepository repository;
@Required
public void setRepository(AccountRepository repository) {}
...
}
<bean name="accountService" class="AccountServiceImpl">
<property name="repository" ref="accountRepository"/>
</bean>
75. 75 | GEEK ACADEMY 2013
@Scope
@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class AccountServiceImpl implements AccountService {
...
}
76. 76 | GEEK ACADEMY 2013
@Lazy & @DependsOn
@Lazy
@Service
@DependsOn({"orderService", "currencyService"})
public class AccountServiceImpl implements AccountService {
...
}
77. 77 | GEEK ACADEMY 2013
Factory method component
@Component
public class CurrencyRepositoryFactory {
@Bean
@Lazy
@Scope("prototype")
@Qualifier("public")
public CurrencyRepository getCurrencyRepository() {
return new CurrencyMapRepository();
}
}
78. 78 | GEEK ACADEMY 2013
JSR 250 @Resource
public class AccountServiceImpl {
@Resource(name = "orderService")
private OrderService orderService;
@Resource(name = "orderService")
public void setOrderService(OrderService orderService) {}
@Resource
private AuditService auditService;
@Resource
public void setAuditService(AuditService auditService) {}
...
}
If no name is specified explicitly, the default name is derived from the field name or setter method.
If no explicit name specified, and similar to @Autowired, @Resource finds a primary type match instead of a specific named bean.
Matches by Name → Matches by Type → Restricts by Qualifiers (ignored if match is found by name)
79. 79 | GEEK ACADEMY 2013
Spring Annotation vs JSR-330
Spring JSR-330
@Autowired @Inject Has no 'required' attribute
@Component @Named
@Scope @Scope Only for meta-annotations and injection points
@Scope @Singleton Default scope is line 'prototype'
@Qualifier @Named
@Value X
@Required X
@Lazy X
80. 80 | GEEK ACADEMY 2013
JSR 330
@Named
@Singleton
public class AccountServiceImpl implements AccountService {
@Inject
private AccountRepository repository;
@Inject
public AccountServiceImpl(@Named("default") AccountRepository r) {}
@Inject
public void setAccountRepository(AccountRepository repository) {}
...
}
@Inject Matches by Type → Restricts by Qualifiers → Matches by Name
81. 81 | GEEK ACADEMY 2013
Classpath scanning and managed components
• Basic Configuration
<!-- looks for annotations on beans -->
<context:annotation-config/>
<!-- scan stereotyped classes and register BeanDefinition -->
<context:component-scan
base-package="org.bank.service,org.bank.repository">
83. 83 | GEEK ACADEMY 2013
Java-based container configuration
• Annotation-based configuration metadata
@Configuration
public class BankConfg {
@Bean
public TransferService createTransferService() {
return new TransferServiceImpl();
}
@Bean(name = "exchangeService", initMethod = "init")
public Exchange createExchangeService() {
return new ExchangeServiceImpl();
}
}
84. 84 | GEEK ACADEMY 2013
Java-based container configuration
ApplicationContext context
= new AnnotationConfigApplicationContext(BankConfig.class);
• Instantiating a container
– Scanning
ApplicationContext context = new AnnotationConfigApplicationContext();
context.scan("org.bank.config");
context.refresh();
85. 85 | GEEK ACADEMY 2013
@Import
@Configuration
@Import({RepositoryConfig.class, ServiceConfig.class})
public class BankConfig {
...
}
@Configuration
public class RepositoryConfg {
...
}
@Configuration
public class ServiceConfig {
...
}
86. 86 | GEEK ACADEMY 2013
@ImportResources
@Configuration
@ImportResource("classpath:spring-master.xml")
public class BankConfig {
@Value("${jdbc.url}")
private String jdbcUrl;
@Bean
public DataSourse dataSource() {
return new SimpleDataSource(jdbcUrl);
}
}
jdbc.url=jdbc:derby://localhost:1527/test
jdbc.user=admin
jdbc.password=password
<context:property-placeholder
location="classpath:META-INF/jdbc.properties" />
Properties
placeholders
87. 87 | GEEK ACADEMY 2013
Dependency injection
@Configuration
public class BankServiceConfig {
@Autowired
private CurrencyRepository currencyRepository;
@Bean
public CurrencyService currencyService() {
return new CurrencyServiceImpl(currencyRepository);
}
@Bean(name = {"orderBuilder", "builder"})
public OrderBuilder orderBuilder() {
return new OrderBuilder(currencyService());
}
}
88. 88 | GEEK ACADEMY 2013
Approach to configuration
• XML
– infrastructure beans
• Annotations
– working beans
• Java
– an alternative to the FactoryBean