摘要:之旅简化开发的使命简化开发为了降低开发的复杂性,采取如下关键策略基于的轻量级和最小侵入性编程通过依赖注入和面向接口实现松耦合基于切面和惯例进行声明式编程通过切面和模版减少样式代码依赖注入耦合性具有两面性一方面,紧密耦合的代码难以测试难以复
Spring之旅 简化Java开发
Spring的使命:简化Java开发
为了降低Java开发的复杂性,采取如下关键策略:
基于POJO的轻量级和最小侵入性编程
通过依赖注入和面向接口实现松耦合
基于切面和惯例进行声明式编程
通过切面和模版减少样式代码
* 耦合性具有两面性(two-headed beast).
一方面,紧密耦合的代码难以测试、难以复用、难以理解,并且典型地表现“打地鼠”式的bug特性(修复一个bug,将会出现一个或者更多新的bug) 另一方面,一定程度的耦合又是必须的--完全没有耦合的代码什么也做不了
* 通过DI,对象的依赖关系将由系统中负责协调各对象的第三方租件在创建对象的时候进行设定。对象无需自行创建或管理它们依赖关系,依赖关系将被自动
注入到需要它们的对象当中去
* 依赖注入会将所依赖的关系自动交给目标对象,而不是让对象自己去获取依赖
构造器注入(constructor injection)
创建应用组件之间协作的行为通常称为装配(wiring)
SlayDragonQuestBraveKnightPrintStream如何装配起来?
XML(knights.xml)和Java描述配置(KnightConfig)
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 基于Java的配置 * * @Configuration注解表明这个类是一个配置类,该类应该包含在Spring应用上下文中如何创建bean的细节 */ @Configuration public class KnightConfig { @Bean public Knight knight(){ return new BraveKnight(quest()); } @Bean public Quest quest(){ return new SlayDragonQuest(System.out); } } import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; /** * 应用上下文容器的demo * */ public class ApplicationContextDemo { //在指定的文件系统中查找knight.xml文件 ApplicationContext context_1 = new FileSystemXmlApplicationContext("c:/knight.xml"); //从所有的类路径下查找knight.xml文件 ApplicationContext context_2 = new ClassPathXmlApplicationContext("knight.xml"); //从Java配置中加载应用上下文 ApplicationContext context_3 = new AnnotationConfigApplicationContext(com.leaf.u_spring.chapter01.KnightConfig.class); }应用切面
DI能够让相互协作的软件组织保持松耦合,而面向切面编程(aspect-oriented programming, AOP)允许你把遍布应用各处的功能分离出来形成可重用的组件
关注点是横切面,如将安全、事务和日志关注点和核心业务逻辑相分离
使用模板消除样板式代码样板式代码(boilerplate code)
import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; /** * 样板式代码(boilerplate code) * 模拟JDBC操作 * */ public class BoilerplateCode { DataSource dataSource = null; String sql = "select id, firstname, lastname, salary from employee where id=?"; //改造前 public Employee getEmployeeById(long id){ Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = dataSource.getConnection(); //查找员工 stmt = conn.prepareStatement(sql); 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) { e.printStackTrace(); } } if(stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return null; } private JdbcTemplate jdbcTemplate; //改造后 //模板能够让你的代码关注于自身的职责 public Employee getEmployeeById_1(long id){ //SQL查询 return jdbcTemplate.queryForObject(sql, new RowMapperSpring 容器(){ //将结果匹配为对象 @Override public Employee mapRow(ResultSet rs, int rowNum) throws SQLException { Employee 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); } } class Employee { private Long id; private String firstName; private String lastName; private BigDecimal salary; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public BigDecimal getSalary() { return salary; } public void setSalary(BigDecimal salary) { this.salary = salary; } }
在基于Spring的应用中,你的应用对象生存于Spring容器(container)中。
Spring容器负责创建对象,装配它们,配置它们并管理它们的整个生命周期,从生存到死亡(new到finalize)
应用上下文,Spring容器的一种
AnnotationConfigApplicationContext:从一个或多个基于Java的配置类中加载Spring应用上下文
AnnotationConfigWebApplicationContext:从一个或多个基于Java的配置类中加载Spring Web应用上下文
ClassPathXmlApplicationContext:从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源
FileSystemXmlApplicationContext:从文件系统下的一个或多个XML配置文件中加载上下文定义
XmlWebApplicationContext:从Web应用下的一个或多个XML配置文件中加载上下文定义
bean的生命周期
Spring对bean进行实例化
Spring将值和bean的引用注入到bean对应的属性中
如果bean实现了BeanNameAware接口,Spring将bean的ID传递给setBeanName()方法
如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传入进来
如果bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessBeforeInitialization()方法
如果bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet()方法。
类似地,如果bean使用了init-method声明了初始化方法,该方法也会被调用
如果bean实现了BeanPostProcessor接口,Spring将调用它们的afterProcessBeforeInitialization()方法
此时,bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁
如果bean实现了DisposableBean接口,Spring将调用它的destroy()接口方法。
同样,如果bean使用destory-method声明了销毁方法,该方法也会被调用
在Spring4.0中,Spring框架的发布版包括了20个不同的模块,每个模块会有3个JAR文件(二进制类库、源码的JAR文件以及JavaDoc的JAR文件)
Spring核心容器,bean工厂、应用上下文等
Spring的AOP模块,AOP、Aspects
数据访问和集成,JDBC、Transaction、ORM、OXM、Messaging、JMS
WEB与远程调用,WEB、WEB servlet、WEB portlet、WebSocket
Instrumentation,为Tomcat提供了一个织入代理,能够为Tomcat传递类文件
Spring PortfolioSpring Web Flow ,为基于流程的会话式Web应用提供了支持
Spring Web Service
Spring Security,利用Spring AOP,Spring Security为Spring应用提供了声明式的安全机制
Spring Integration,提供了多种通用应用集成模式的Spring声明式风格实现
Spring Batch
Spring Data 支持关系型数据库和非关系型数据库
Spring Social 社交网络扩展模块
Spring Mobile移动应用
Spring for Android
Spring Boot大量依赖于自动配置技术
Spring 3.1新特性引入环境profile功能,解决各种环境(开发、测试、生产)选择不通配置的问题
添加了多个enable注解,注解启用Spring的特定功能
添加了Spring对声明式缓存的支持,能够使用简单的注解声明缓存边界和规则
新添加的用于构造器注入的c命名空间
开始支持Servlet3.0,包括基于Java的配置中声明Servlet和Filter
改善对JPA的支持
自动绑定路径变量到模型属性中
提供了@RequestMappingproduces和consumes属性,用于匹配请求中的Accept和Content-Type头部信息
提供了@RequestPart注解,用于将multipart请求中的某些部分绑定到处理器的方法参数中
支持flash属性以及用于在请求间存放flash属性的RedirectAttributes类型
Spring 3.2新特性可以使用Servlet3.0的异步请求
引入了Spring MVC测试框架
基于RestTemplate的客户端的测试支持
@ControllerAdvice注解能够将通用的@ExceptionHandler、@InitBinder和@ModelAttributes方法集中到一个类中,并应用到所有控制器上
支持完整的内容协商(full content negotiation)
@MatrixVariable注解能绑定矩阵变量到方法参数中
基础的抽象类AbstractDispatcherServletInitializer能够非常便利地配置DispatcherServlet
新增了ResponseEntityExceptionHandler
RestTemplate和@RequestBody的参数可以支持泛型
RestTemplate和@RequestMapping可以支持HTTP PATCH方法
在拦截器匹配时,支持使用URL模式将其排除在拦截器的处理功能之外
@Autowired @Value @Bean
@DateTimeFormat
提供了对JCache5.0的支持
支持定义全局来解析和渲染日期和时间
在集成测试中,能够配置和加载WebApplicationContent
在集成测试中,能够针对request和session作用域的bean进行测试
Spring 4.0 新特性支持WebSocket
提供高层次的面向消息的编程模型,基于SockJS
支持Java8特性
添加了条件化创建bean的功能
包含了Spring RestTemplate的一个新的异步实现
Spring 致力于简化企业级Java开发,促进代码的松散耦合
依赖注入和AOP是Spring框架最核心的部分
引用:《Spring In Action 4》第1章
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/70887.html
摘要:基于上的我们还可以实现几个基于的,还是老样子,先让我们创建两个好了,现在我们想要实现两个的,但是条件是通过的和的这样我们也可以得到结果。 Merge, Join, Concat 大家好,我有回来啦,这周更新的有点慢,主要是因为我更新了个人简历哈哈,如果感兴趣的朋友可以去看看哈: 我的主页 个人认为还是很漂亮的~,不得不说,很多时候老外的设计能力还是很强。 好了,有点扯远了,这一期我想和...
摘要:除了,还简单介绍了对的支持,可以帮助应用将散落在各处的逻辑汇集于一处切面。当装配的时候,这些切面能够运行期编织起来,这样就能呢个非常有效的赋予新功能。 第1章 Spring之旅 说明 1、本文参考了《Spring 实战》重点内容,参考了GitHub上的代码 2、每个人的学习方式不一样,但目的是一样的,活学活用。最近一直在听《我们不一样》 3、本文只为记录作为以后参考,要想真正领悟Sp...
摘要:的版本增加了对事件监听程序的支持,事件监听程序在建立修改和删除会话或环境时得到通知。元素指出事件监听程序类。过滤器配置将一个名字与一个实现接口的类相关联。 1.简介 web.xml文件是Java web项目中的一个配置文件,主要用于配置欢迎页、Filter、Listener、Servlet等,但并不是必须的,一个java web项目没有web.xml文件照样能跑起来。Tomcat容器/...
阅读 1922·2021-09-07 09:59
阅读 2494·2019-08-29 16:33
阅读 3591·2019-08-29 16:18
阅读 2808·2019-08-29 15:30
阅读 1633·2019-08-29 13:52
阅读 1999·2019-08-26 18:36
阅读 481·2019-08-26 12:19
阅读 657·2019-08-23 15:23