Spring Core Tutorials
Spring bean scopes
概念
example
xml:
1 2 3 4 5 6 7 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-2.5.xsd"> <bean id="demoBean" class="com.howtodoinjava.application.web.DemoBean" scope="session" /> </beans>
|
annotation:
1 2 3 4 5 6
| @Service @Scope("session") public class DemoBean { }
|
Spring bean life cycle
Spring框架提供4种控制bean生命周期的方式。
- InitializingBean和DisposableBean回调接口
- 其它特定行为的Aware接口
- 配置文件中使用init()和destroy()方法
- @PostConstruct和@PreDestroy注解
InitializingBean和DisposableBean回调接口
不推荐使用,因为与Spring框架紧密耦合。
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; public class DemoBeanTypeOne implements InitializingBean, DisposableBean { @Override public void afterPropertiesSet() throws Exception { } @Override public void destroy() throws Exception { } }
|
配置文件中使用init()和destroy()方法
推荐
Example
1 2 3
| <beans> <bean id="demoBean" class="com.howtodoinjava.task.DemoBean" init-method="customInit" destroy-method="customDestroy"></bean> </beans>
|
全局制定
1 2 3
| <beans default-init-method="customInit" default-destroy-method="customDestroy"> <bean id="demoBean" class="com.howtodoinjava.task.DemoBean"></bean> </beans>
|
@PostConstruct和@PreDestroy注解
@PostConstruct在对象调用构造函数之后,在返回给请求对象之前调用。
@PreDestroy在Bean被容器销毁之前调用。
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; public class BemoBeanTypeFour { @PostConstruct public void customInit() { System.out.println("Method customInit() invoked..."); } @PreDestroy public void customDestroy() { System.out.println("Method customDestroy() invoked..."); } }
|
Spring Beans Autowiring
Example
xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.howtodoinjava" /> <bean id="employee" class="com.howtodoinjava.demo.beans.EmployeeBean" autowire="byName"> <property name="fullName" value="Lokesh Gupta"/> </bean> <bean id="departmentBean" class="com.howtodoinjava.demo.beans.DepartmentBean" > <property name="name" value="Human Resource" /> </bean> </beans>
|
annotation:
首先必须开启注解
1
| <context:annotation-config />
|
或者注入Autowire的注解处理器
1
| <bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
|
Example
@Autowired
可以在field
,setting
,constructor
上使用。byType
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class EmployeeBean { @Autowired private DepartmentBean departmentBean; public DepartmentBean getDepartmentBean() { return departmentBean; } public void setDepartmentBean(DepartmentBean departmentBean) { this.departmentBean = departmentBean; } }
|
使用@Qualifier
解决冲突
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class EmployeeBean { @Autowired @Qualifier("finance") private DepartmentBean departmentBean; public DepartmentBean getDepartmentBean() { return departmentBean; } public void setDepartmentBean(DepartmentBean departmentBean) { this.departmentBean = departmentBean; } }
|
1 2 3 4 5 6 7 8 9
| <bean id="humanResource" class="com.howtodoinjava.autowire.constructor.DepartmentBean" > <property name="name" value="Human Resource" /> </bean> <bean id="finance" class="com.howtodoinjava.autowire.constructor.DepartmentBean" > <property name="name" value="Finance" /> </bean>
|
使用required=false可选关联
1 2 3
| @Autowired (required=false) @Qualifier ("finance") private DepartmentBean departmentBean;
|
Loading External Resources
可以实现ApplicationContextAware或者ResourceLoaderAware
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; public class CustomResourceLoader implements ResourceLoaderAware { private ResourceLoader resourceLoader; public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } public void showResourceData() throws IOException { Resource banner = resourceLoader.getResource("file:c:/temp/filesystemdata.txt"); InputStream in = banner.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); while (true) { String line = reader.readLine(); if (line == null) break; System.out.println(line); } reader.close(); } }
|
1
| Resource banner = resourceLoader.getResource("file:data.txt");
|
1
| Resource banner = resourceLoader.getResource("classpath:classpathdata.txt");
|
1
| Resource banner = resourceLoader.getResource("file:c:/temp/filesystemdata.txt");
|
1
| Resource banner = resourceLoader.getResource("http://howtodoinjava.com/readme.txt");
|
@Component, @Repository, @Service and @Controller annotations
@Component 当开启组件自动扫描时,将一个java类成为bean组件
@Repository 将DAO注入,同时,将非检查异常替代为更合理的DateAccessException
@Service 将servcie注入
@Controller 将controller注入
Example
1 2 3
| <context:component-scan base-package="com.howtodoinjava.demo.service" /> <context:component-scan base-package="com.howtodoinjava.demo.dao" /> <context:component-scan base-package="com.howtodoinjava.demo.controller" />
|
1 2 3 4 5 6 7 8 9 10 11
| @Controller ("employeeController") public class EmployeeController { @Autowired EmployeeManager manager; public EmployeeDTO createNewEmployee() { return manager.createNewEmployee(); } }
|
Inversion of Control(IOC)
控制反转是面向对象编程中的一种设计原则,通过依赖注入,降低对象之间的耦合度。
通过定义对象之间的抽象关系,在运行期,通过容器注入对象实例。
其中BeanFactory是IOC的容器的核心。
三种bean实例化方法
1 2
| //构造方法 <bean id="exampleBean"/>
|
1 2
| //静态工厂 <bean id="exampleBean" factory-method="createInstance"/>
|
1 2 3 4 5
| //普通工厂方法 <bean id="myFactoryBean" class="..."> <bean id="exampleBean" factory-bean="myFactoryBean" factory-method="createInstance"></bean>
|
BeanFacotry和ApplicationContext
BeanFactory加载bean的定义
,实例化bean
。维护对象直接的关系,管理bean的生命周期
。
ApplicationContext在BeanFacotory的基础上,增加了text messages
, load file resources
, register events as listeners
常用的ApplicationContext
1 2
| ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml”); ApplicationContext context = new FileSystemXmlApplicationContext(“bean.xml”);
|
Spring REST JSON
只需要引用jackson
到类路径,spring会自动注册Jackson2JsonMessageConvter
。当客户端请求时,提供http头部:accept:application/json
,就可以返回jason格式的数据。
1 2 3 4 5 6
| <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.4.1</version> </dependency>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @RestController = @Controller + @ResponseBody @RestController public class EmployeeRESTController { @RequestMapping(value = "/employees/{id}") public ResponseEntity<EmployeeVO> getEmployeeById (@PathVariable("id") int id) { if (id <= 3) { EmployeeVO employee = new EmployeeVO(1,"Lokesh","Gupta","howtodoinjava@gmail.com"); return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK); } return new ResponseEntity(HttpStatus.NOT_FOUND); } }
|
返回json视图
1 2 3 4 5 6 7 8 9 10
| @Controller public class EmployeeRESTController { @RequestMapping(value = "/employees") public String getAllEmployeesJSON(Model model) { model.addAttribute("employees", getEmployeesCollection()); return "jsonTemplate"; } }
|
更改配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Configuration public class RESTConfiguration { @Bean public View jsonTemplate() { MappingJackson2JsonView view = new MappingJackson2JsonView(); view.setPrettyPrint(true); return view; } @Bean public ViewResolver viewResolver() { return new BeanNameViewResolver(); } }
|
或者XML
1 2 3
| <bean name="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/> <bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
|
Spring Rest XML
引入jackson
1 2 3 4 5 6
| <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.4.1</version> </dependency>
|
web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>spring</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
|
spring-servlet.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context/ http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.howtodoinjava.demo" /> <mvc:annotation-driven /> </beans>
|
EmployeeVO.java
Java内置了JAXB,会自动加载JaxbRootElementHttpMessageConverter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| import java.io.Serializable; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement (name = "employee") @XmlAccessorType(XmlAccessType.NONE) public class EmployeeVO implements Serializable { private static final long serialVersionUID = 1L; @XmlAttribute private Integer id; @XmlElement private String firstName; @XmlElement private String lastName; @XmlElement private String email; public EmployeeVO(Integer id, String firstName, String lastName, String email) { super(); this.id = id; this.firstName = firstName; this.lastName = lastName; this.email = email; } public EmployeeVO(){ } @Override public String toString() { return "EmployeeVO [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]"; } }
|
controller
@RestController表示返回的结果作为body
JAXB指定返回XML
通过ResponseEntity封装,可以返回HTTP状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import com.howtodoinjava.demo.model.EmployeeListVO; import com.howtodoinjava.demo.model.EmployeeVO; @RestController public class EmployeeRESTController { @RequestMapping(value = "/employees/{id}") public ResponseEntity<EmployeeVO> getEmployeeById (@PathVariable("id") int id) { if (id <= 3) { EmployeeVO employee = new EmployeeVO(1,"Lokesh","Gupta","howtodoinjava@gmail.com"); return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK); } return new ResponseEntity(HttpStatus.NOT_FOUND); } }
|
Spring RestTemplate
controller
1 2 3 4 5 6 7 8 9
| @RequestMapping(value = "/employees/{id}") public ResponseEntity<EmployeeVO> getEmployeeById (@PathVariable("id") int id) { if (id <= 3) { EmployeeVO employee = new EmployeeVO(1,"Lokesh","Gupta","howtodoinjava@gmail.com"); return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK); } return new ResponseEntity(HttpStatus.NOT_FOUND); }
|
使用RestTemplate
1 2 3 4 5 6 7 8 9 10 11 12
| private static void getEmployeeById() { final String uri = "http://localhost:8080/springrestexample/employees/{id}"; Map<String, String> params = new HashMap<String, String>(); params.put("id", "1"); RestTemplate restTemplate = new RestTemplate(); EmployeeVO result = restTemplate.getForObject(uri, EmployeeVO.class, params); System.out.println(result); }
|
Spring Email
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context/ http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.howtodoinjava" /> <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.gmail.com"/> <property name="port" value="25"/> <property name="username" value="howtodoinjava@gmail.com"/> <property name="password" value="password"/> <property name="javaMailProperties"> <props> <prop key="mail.transport.protocol">smtp</prop> <prop key="mail.smtp.auth">true</prop> <prop key="mail.smtp.starttls.enable">true</prop> <prop key="mail.debug">true</prop> </props> </property> </bean> <bean id="preConfiguredMessage" class="org.springframework.mail.SimpleMailMessage"> <property name="to" value="somebody@gmail.com"></property> <property name="from" value="howtodoinjava@gmail.com"></property> <property name="subject" value="FATAL - Application crash. Save your job !!"/> </bean> </beans>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.MailSender; import org.springframework.mail.SimpleMailMessage; import org.springframework.stereotype.Service; @Service("mailService") public class ApplicationMailer { @Autowired private MailSender mailSender; @Autowired private SimpleMailMessage preConfiguredMessage; * This method will send compose and send the message * */ public void sendMail(String to, String subject, String body) { SimpleMailMessage message = new SimpleMailMessage(); message.setTo(to); message.setSubject(subject); message.setText(body); mailSender.send(message); } * This method will send a pre-configured message * */ public void sendPreConfiguredMail(String message) { SimpleMailMessage mailMessage = new SimpleMailMessage(preConfiguredMessage); mailMessage.setText(message); mailSender.send(mailMessage); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; public class MailerTest { public static void main(String[] args) { ApplicationContext context = new FileSystemXmlApplicationContext("application-context.xml"); ApplicationMailer mailer = (ApplicationMailer) context.getBean("mailService"); mailer.sendMail("somebody@gmail.com", "Test Subject", "Testing body"); mailer.sendPreConfiguredMail("Exception occurred everywhere.. where are you ????"); } }
|