Spring
Spring
Spring具有控制反转(IoC)和面向切面(AOP)两大核心。Java Spring 框架通过声明式方式灵活地进 行事务的管理,提高开发效率和质量。
Spring 框架不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可 以从 Spring 中受益。Spring 框架还是一个超级粘合平台,除了自己提供功能外,还提供粘合其他技术 和框架的能力。
Spring体系结构
1.核心容器
核心容器由Spring-core, Spring-beans, Spring-context ,Spring-context-support,Spring-excepression(SpEL,spring表达式语言,Spring Expression Language)等模块组成。
-
Spring-core 提供了框架的基本组成部分,包括IoC和依赖注入功能。
-
Spring-beans 提供了BeanFactory,工厂模式的精妙实现,移除了编码式单例的需要,并且可以把配置和依赖从实际编码逻辑中解耦。
-
context 建立在由core和beans模块的基础上建立起来的,它以一种类似于JNDI(
)注册的方式访问对象。Context模块继承于Bean模块,并添加了国际化,事件传播,资源加载和透明的创建Context(比如创建Servlet容器)。Context模块也支持JavaEE的功能,比如EJB(
),JMX((Java Management Extensions)是一个为应用程序植入管理功能的框架)和远程调用.ApplicationContext接口是Context模块的焦点。
-
Spring-context-support提供了对第三方集成到Spring上下文的支持,比如EhCache(一个纯java的进程内缓存),Guava(开源免费的Java工具集),JavaMail(是sun公司(现以被甲骨文收购)为方便Java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,它支持一些常用的邮件协议,如前面所讲的SMTP,POP3,IMAP,还有MIME等),CommonJ(是BEA和IBM联合推出的一个规范,其目的是为了给开发人员在开发可移植的服务端应用程序时提供一些更加简单和功能更加强大的方法),Quartz(是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务,类似于java.util.Timer),
FreeMarker(是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具),JasperReports(是一个非常强大,易用的开源报表引擎,它是用Java编写的。它可以通过各种各样的数据源来生成像素级的文档,这些文档都可以查看,打印以及导出(文档格式包括HTML、PDF、Excel、Word等等)),Velocity(是一个基于java的模板引擎(template engine),它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。它作为一款成熟的基于java的模板引擎,能够帮我们实现页面静态化,同时它将Java代码与网页分开,使网站在其生命周期内更加可维护,并为Java Server Pages(JSP)或PHP提供了可行的替代方案)
-
Spring-expression 提供了强大的表达式语言,用于在运行时查询和操作对象图。它是 JSP2.1 规范中定义的统一表达式语言的扩展,支持 set 和 get 属性值、属性赋值、方法调用、访问数组集合及索引的内容、逻辑算术运算、命名变量、通过名字从 Spring IoC 容器检索对象,还支持列表的 投影、选择以及聚合等。
依赖关系如下图:
2. 数据访问/集成
JDBC=Java Data Base Connectivity,ORM=Object Relational Mapping,OXM=Object XML Mapping,JMS=Java Message Service
-
JDBC 模块提供了 JDBC 抽象层,它消除了冗长的 JDBC 编码和对数据库供应商特定错误代码的解析。
-
ORM 模块提供了对流行的对象关系映射API的集成,包括JPA(JPA顾名思义就是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中),JDO(Java Data Object 是 Java 对象持久化的新规范,也是一个用于存取某种数据仓库的对象的标准化API)和Hibernate(也是一种ORM框架)
-
JMS模块包含生产和消费消息功能。从Spring4.1开始,集成了Spring-messaging 模块。
-
事务模块为实现特殊接口类及所有的POJO支持编程式和声明式事务管理。
3.Web
-
Web模块提供了面向Web的基本功能和面向web的应用容器,比如多部份的multipart文件上传功能,使用Servlet监听器初始化IoC容器等。它还包括HTTP客户端以及Spring远程调用中与web相关的部分。
-
Web_MVC 模块为web应用提供了MVC和REST web服务的实现。Srping的MVC可以使领域模型代码和web表单完全地分离,且可以与Spring框架的其他功能进行集成。
-
Web-Socket 模块为WebSocket-based 提供了支持,而且在web应用中提供了客户端和服务器端之间通信的两种方式。
-
Web-Portlet 模块提供了用于Portlet(由基于java的web组件,由portlet容器管理,并由容器处理请求,生产动态内容) 环境的MVC实现,并反映了Spring-webmvc模块的功能。
4.其他
-
AOP模块提供了面向切面的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦,从而使实现功能地代码彻底解解耦出来。
-
AspectJ模块提供了与ApectJ的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架。
-
Instrumentation 模块在一定的应用服务器中提供了类instrmentation 的支持和类加载器的是实现。
-
Messaging模块为STOMP 提供了支持作为在应用程序中WebSocket子协议的使用。它也支持一个注解编程模型,它是为了选路和处理来自websocket客户端的STOMP信息。
-
测试模块支持对具有JUnit 或 TestNG 框架的Spring 组件的测试。
2、Spring核心之IoC控制反转
2.1 IoC的概念
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。 IoC 是指在程序开发中,实例的创建不再由调用者管理,而是由 Spring 容器创建。Spring 容器会负责控 制程序之间的关系,而不是由程序代码直接控制,因此,控制权由程序代码转移到了 Spring 容器中,控制权发生了反转,这就是 Spring 的 IoC 思想。
2.2 获取Spring 容器
Spring 提供了两种IoC 容器,分别为 BeaFactory 和 ApplicationContext
BeanFactory是基础类的IoC容器,是一个管理Bean的工厂,它只要负责初始化各种Bean,并调用它们的生命周期方法。
ApplicationContext是BeanFactory的子接口,不仅提供了BeanFactory的所有功能,还添加了对国际化,资源访问,事件传播等方面的良好支持。
ApplicationContext有两个常见的实现类:
ClassPathXMlApplicationContext(常用)
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(Spring配
置文件的名称);
<bean id="person" class="service.Person">
<!-- 控制器调用setAxe方法,将容器中的axe bean作为传入的参数 -->
<!--此处的name是决定Person类中的那个参数,ref是指bean配置文件中的bean名称-->
<property name="axe" ref="axe"></property>
</bean>
记得在web.xml中配置ContextLoaderListenter
ContextLoaderListener的作用就是启动Web容器时,读取在contextConfigLocation中定义的xml文件,自动装配ApplicationContext的配置信息,并产生WebApplicationContext对象,然后将这个对象放置在ServletContext的属性里,这样我们只要得到Servlet就可以得到WebApplicationContext对象,并利用这个对象访问spring容器管理的bean。
简单来说,就是上面这段配置为项目提供了spring支持,初始化了Ioc容器。
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
2.3 基于XML的DI
DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即 由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为 了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过 简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资 源来自何处,由谁实现
2.3.1 注入分类
bean 实例在调用无参构造器创建对象后,就要对 bean 对象的属性进行初始化。初始化是由容器自动完 成的,称为注入。
2.3.1.1 通过set方法 set 注入也叫设值注入是指,通过 setter 方法传入被调用者的实例。这种注入方式简单、直观,因而在 Spring 的依赖注入中大量使用。
2.3.1.2 通过构造方法 构造注入是指,在构造调用者实例的同时,完成被调用者的实例化。使用构造器设置依赖关系。
2.3.1.3. 自动注入 对于引用类型属性的注入,也可不在配置文件中显示的注入。可以通过为标签 设置 autowire 属性值,为引用类型属性进行隐式自动注入(默认是不自动注入引用类型属 性)。根据 自动注入判断标准的不同,可以分为两种:
byName:根据名称自动注入
byType: 根据类型自动注入
用法如图:
2.4自动注入
@Autowired() 中的required为false时,如果@Qualifier中的类找不到就会返回空,反之就会报错。
2.5 注解实现IoC
@Component声明普通Bean
除此之外,Spring中还提供了其他3个用于创建对象的注解:
@Repository : 用于dao实现类的的注解 @Service: 用户service实现类的注解 @Controller: 用于controller实现类的注解 这三个注解与@Component 都可以创建对象,但这三个注解还有其他的含义,@Service创建业务层对 象,业务层对象可以加入事务功能,@Controller 注解创建的对象可以作为处理器接收用户的请求。 @Repository,@Service,@Controller 是对@Component 注解的细化,标注不同层的对象。即持久 层对象,业务层对象,控制层对象
3.1 Spring-Aop
Spring的AOP实现底层就是对上面的动态代理的代码进行了封装,封装后我们只需要对需要关注的部分 进行代码编写,并通过配置的方式完成指定目标的方法增强。
我们先来介绍AOP的相关术语:
Target(目标对象) 要被增强的对象,一般是业务逻辑类的对象。
Proxy(代理) 一个类被 AOP 织入增强后,就产生一个结果代理类。
Aspect(切面) 表示增强的功能,就是一些代码完成的某个功能,非业务功能。是切入点和通知的结合。
Joinpoint(连接点) 所谓连接点是指那些被拦截到的点。在Spring中,这些点指的是方法(一般是类中的业务方法),因为 Spring只支持方法类型的连接点。
Pointcut(切入点) 切入点指声明的一个或多个连接点的集合。通过切入点指定一组方法。 被标记为 final 的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。
Advice(通知/增强) 所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。通知定义了增强代码切入到目标代码的时 间点,是目标方法执行之前执行,还是之后执行等。通知类型不同,切入时间不同。 通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。 切入点定义切入的位置,通知定义切入的时间。
Weaving(织入). 是指把增强应用到目标对象来创建新的代理对象的过程。 spring 采用动态代理织入,而 AspectJ 采用编 译期织入和类装载期织入。
切面的三个关键因素:
1、切面的功能–切面能干啥
2、切面的执行位置–使用Pointcut表示切面执行的位置
3、切面的执行时间–使用Advice表示时间,在目标方法之前还是之后执行
3.2AspectJ 对AOP的实现
3.2.1类型
-
前置通知
-
后置通知
-
环绕通知
-
异常通知
-
最终通知
3.2.2 切入点表达式
AspectJ 定义了专门的表达式用于指定切入点。
表达式的原型如下:
execution(modifiers-pattern? ret-type-pattern
declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)
说明:
modifiers-pattern] 访问权限类型
ret-type-pattern 返回值类型
declaring-type-pattern 包名类名
name-pattern(param-pattern) 方法名(参数类型和参数个数)
throws-pattern 抛出异常类型
?表示可选的部分
3.3 使用注解实现
@Aspect 标识当前类是一个切面类
/**
* 当较多的通知增强方法使用相同的 execution 切入点表达式时,编写、维护均较为麻烦。
* AspectJ 提供了@Pointcut 注解,用于定义 execution 切入点表达式。
* 其用法是,将@Pointcut 注解在一个方法之上,以后所有的 execution 的 value 属性值均
* 可使用该方法名作为切入点。代表的就是@Pointcut 定义的切入点。
* 这个使用@Pointcut 注解方法一般使用 private 的标识方法,即没有实际作用的方法。
*/
@Pointcut("execution(* com.kkb.service..*.*(..))")
private void pointCut(){
}
@Pointcut("execution(* com.kkb.service..*.add*(..))")
private void pointCut2(){
}
@Before 前置
@AfterReturning 后置
@Around 环绕
@AfterThrowing 异常
@After 最终
3.4 xml配置
注册aspectJ的自动代理
<aop:aspect-autoproxy proxy-target-class="true"/>
4 Spring 整合JDBC
学习使用jdbc Template API 和 如何使用Spring 管理jdbc Template
4.1
spring的配置文件application.xml中需要创建数据源和给TeamDao中的jdbcTemplate赋值
创建数据源
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver">
</property>
<property name="jdbcUrl"
value="jdbc:mysql://192.168.58.128:3306/springJDBC?
serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=fal
se"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
创建Template
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
需要注入数据源
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="teamDao" class="com.kkb.dao.TeamDao">
<!--需要JdbcTemplate-->
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
5 Spring 事务管理
事务原本是数据库中的概念,在 Dao 层。但在实际开发中,一般将事务提升到业务层,即 Service 层。 这样做是为了能够使用事务的特性来管理具体的业务。
5.1 事务管理器接口
事务管理器是 PlatformTransactionManager 接口对象。其主要用于完成事务的提交、回滚,及获取事 务的状态信息。
PlatformTransactionManager 接口常用的实现类: DataSourceTransactionManager:使用 JDBC 或 MyBatis 进行数据库操作时使用。
Spring 事务的默认回滚方式是:发生运行时异常和 error 时回滚,发生受查(编译)异常时提交。不过, 对于受查异常,程序员也可以手工设置其回滚方式
5.2 实现
5.2.1 基于注解的事务
/**
* @Transactional 属性 说明:
* readOnly:是否只读
*
* rollbackFor={Exception.class}: 遇到什么异常会回滚
*
* propagation事务的传播:
* Propagation.REQUIRED:当前没有事务的时候,就会创建一个新的事务;如果当前有事务,就直
接加入该事务,比较常用的设置
* Propagation.SUPPORTS:支持当前事务,如果当前有事务,就直接加入该事务;当前没有事务的
时候,就以非事务方式执行
* Propagation.MANDATORY:支持当前事务,如果当前有事务,就直接加入该事务;当前没有事务的
时候,就抛出异常
* Propagation.REQUIRES_NEW:创建新事务,无论当前是否有事务都会创建新的
*
* isolation=Isolation.DEFAULT:事务的隔离级别:默认是数据库的隔离级别
*
*/
@Transactional(propagation = Propagation.REQUIRED,rollbackFor =
{Exception.class})
5.2.2 基于XML的事务
<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.kkb.service..*.*
(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
</aop:config>