1. 模块概览

Spring5框架包含许多特性,负责管理项目中的所有对象,并被很好地组织在下图所示的模块中

核心容器:由spring-beans、spring-core、spring-context、spring-expression(SpEL)4个模块组成,如下:

1. spring-bean和spring-core模块是spring框架核心模块,包含了IOC和DI,beanFactory接口是spring框架中的核心接口,是工厂模式的具体体现

2. spring-context模块架构于核心模块之上,扩展了beanFactory,并为之添加了bean生命周期控制、框架事件体系、资源透明化等体系,此外还提供了企业级的支持,

例如邮件发送、远程访问、任务调度等,ApplicationContext是spring-context模块的核心接口,该接口的继承图参加下文;

3. spring-expression模块是统一表达式语言(EL)的扩展模块,最出色的功能是函数调用和简单字符串的模板函数;

AOP和设备支持:由spring-aop、spring-aspects和spring-instrument3个模块组成

1. spring-aop是另一个核心模块,是AOP主要实现模块,在spring中以JVM的动态代理为基础设计出一系列的AOP横切实现,例如:前置通知等,同时Pointcut接口来匹配

切入点,然后使用切入点来设计横切面;

2. spring-aspects模块集成自AspectJ框架,主要是为SpringAOP提供多种AOP实现方法;

3. spring-instrument模块是基于JAVASE中的"java.lang.instrument"进行设计的,是AOP的一个支援模块。作用:在JVM启用时,生成一个代理类,程序员通过代理类

在运行时修改类的字节,从而改变一个类的功能,实现AOP的功能;

数据访问及集成:由spring-jdbc、spring-tx、spring-orm、spring-jms和spring-oxm5个模块组成

1. spring-jdbc模块是Spring提供的JDBC抽象框架的主要实现模块,用于简化JDBC编程,主要实现类是(Simple)JdbcTemplate、NamedParameterJdbcTemplate

2. spring-tx模块是SpringJDBC事务控制实现模块,对事务做了很好的封装,通过它的AOP配置,可以灵活的配置在任何一层;

3. spring-orm模块是ORM框架支持模块,主要集成Hibernate,JPA、JDO用于资源管理、数据访问对象(DAO)的实现和事务策略;

4. spring-jms模块(JavaMessagingService)能够发送和接受信息,自SpringFramework4.1以后,还提供了对spring-messaging模块的支持;

5. spring-oxm模块主要提供一个抽象层以支持OXM(将java对象映射成XML数据,或者将XML数据映射成java对象);

Web:由spring-web、spring-webmvc、spring-websocket和spring-webflux4个模块组成

1. spring-web模块为spring提供了最基础Web支持,主要建立于核心容器之上,通过Servlet或者Listeners来初始化IOC容器,也包含一些与Web相关的支持;

2. spring-webmvc模块众所周知是一个的Web-Servlet模块,实现了SpringMVC(model-view-Controller)的Web应用;

3. spring-websocket模块主要是与Web前端的全双工通讯的协议(个人理解);

4. spring-webflux是一个新的非堵塞函数式ReactiveWeb框架,可以用来建立异步的,非阻塞,事件驱动的服务,扩展性非常好;

报文发送:spring-messaging模块、测试模块:Testspring-test模块

1. spring-messaging是从spring4开始新加入的一个模块,主要职责是为spring框架集成一些基础的报文传送应用

2. spring-test模块主要为测试提供支持的

【参考资料】:Spring各个jar包的详解,以及依赖

2. Maven搭建Spring项目

1. IDEA创建Maven项目

2. 添加Spring依赖

3. Maven添加完spring-context依赖之后,会自动下载5个spring相关的jar

4. 如果通过注解的方式注入bean则需要在classpath下新建resources文件夹(Resource该文件夹),并创建applicationContext.xml;

3. 重要概念

3.1 IOC/DI

IOC:反转控制,之前由开发人员创建、维护对象,包括依赖关系也是由开发人员注入,使用Spring之后,对象的创建以及依赖关系由spring完成

spring1.x & spring2.x:创建对象依靠<bean></bean>

spring3.x+:主要依靠注解管理对象,@Controller、@Service、@Repository、@Component等

DI:依赖注入,实现IOC需要DI支持

spring1.x & spring2.x:依靠<bean></bean>标签实现依赖的注入,如下所示。

spring3.x:依靠注解实现依赖的注入,给属性赋值。@Autowired  @Qualifiered @Resource @Value等

3.2 AOP★

AOP(Aspect Oriented Programming),即面向切面编程,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可

重用模块,命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模

块之间的耦合度,并有利于未来的可操作性和可维护性,如下图所示

AOP的功能完全集成到了Spring事务管理、日志和其他各种特性的上下文中,AOP编程的常用场景有:

Authentication权限认证、Logging日志、TransctionsManager事务、LazyLoading懒加载等

AOP的实现依赖于动态,代理模式有jdk动态代理和cjlib动态代理,其中spring采用cjlib代理

3.3 事务管理

【参考资料】:事务的并发和隔离级别

Spring管理事务属性介绍:1. 事务的隔离级别;2. 是否只读; 3. 事务的传播行为

事务的7种传播行为
事务传播行为类型 说明
PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。(Spring默认)
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行
PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作

4. 功能分析

4.1 Bean元素分析

  4.1.1 前提准备

  4.1.2 单例/多例

scope属性有4种:

  1. singleton 默认值  : 被标识为单例的对象在spring容器中只会存在一个实例.

  2. prototype 多例原型:标识当前对象多例对象,每次在获得才会创建.每次创建都是新的对象.整合struts2时,ActionBean必须配置为多例的.

  3. request: web环境下.对象与request生命周期一致.(基本不用)

  4. session: web环境下,对象与session生命周期一致. (基本不用)

  5. application的作用范围表示从服务器一开始执行任务,到服务器关闭为止,会一直在服务器的内存中存在(基本不用)

  4.1.3 懒加载

lazy-init,告诉spring容器是否以懒加载的方式创造对象。用的时候才加载构造,不用的时候不加载,取值:true、false、default(懒)

懒加载机制只对单例bean有作用,对多例bean,没有意义,多例bean只有在使用的时候才会被加载;

 懒加载与非懒加载的优缺点

  1. 懒加载:对象使用的时候才去创建,节省资源,但是不利于提前发现错误;

  2. 非懒加载:容器启动的时候立刻创建对象。消耗资源,利于提前发现错误;

  3. 当scope=“prototype” (多例)时,默认以懒加载的方式产生对象;

  4. 当scope=“singleton” (单例)时,默认以非懒加载的方式产生对象;

  4.1.4 对象初始化/销毁

生命周期属性:

  init-method:初始化方法. spring会在对象创建之后立即调用

  destroy-method:销毁方法. spring容器在关闭并销毁所有容器中的对象之前调用

【参考资料】:spring中bean的生命周期

  4.1.5 set注入方式★

  4.1.6 构造注入方式

4.2 创建对象方式分析

4.3 AOP分析

  4.3.1 两种代理方式

1. 动态代理:被代理对象必须要实现接口才能产生代理对象,如果没有接口,则不能使用动态代理技术(spring优先使用动态代理)

参考资料】:Java中的动态代理

2. CJLIB代理:第三方代理技术,可对任何类生成代理,代理原理是:对目标对象进行继承代理,如果目标对象被final修饰,该类则无法被cjlib代理

        //创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数
Enhancer enhancer = new Enhancer();
//设置目标类的字节码文件
enhancer.setSuperclass(Dog.class);
//设置回调函数
enhancer.setCallback(new MyMethodInterceptor());
//creat方法就是正式创建代理类
Dog proxyDog = (Dog)enhancer.create();
//调用代理类的eat方法
proxyDog.eat();

3. 两者区别:

1. jdk动态代理必须借助一个接口才能产生代理对象,所以在使用代理之前,先要有一个接口,然后定义一个类实现接口;

2. cjlib动态代理,它的优势在于不用提供接口,只要一个非抽象类就可以实现动态代理;

  4.3.2 AOP名词解释

1. Joinpoit:连接点,目标对象中的方法称为连接点

2. Pointcut:切入点,需要确定哪些连接点需要被增强,因此需要规则,这个规则称为切入点规则,切入点=连接点+切入点规则

3. Aspet:切面,spring拦截下切入点后,将其交给用户定义的处理类进行功能增强,这个用户定义的处理类称为切面

4. Advice: 通知,切面中用户定义的用于增强的代码,包括around、before、after等不同类型的通知

5. Target: 目标对象,被代理的对象

6. Weaving:织入,将通知应用到切入点的过程称之为织入,也就是增强目标方法的过程

  4.3.3 spring中AOP的配置

AOP中的通知有5类:前置通知、后置通知(2)、环绕通知、异常通知

一.通过applicationContext.xml配置通知

1. 首先要自定义一个切面(通知类)

2. 将通知织入目标对象(XML配置)

4.4 spring事务分析

因为在不同平台,操作事务的代码各不相同.spring提供了一个事务操作对象 PlatformTransactionManager 接口,针对不同的数据库有不同的实现类,如下:

  • DataSourceTransactionManager(核心事务管理)
  • HibernateTransitionmanager
  • HibernateTransitionmanager

1. 编码式配置aop事务(略)

2. 通过XML配置aop事务


3. 通过注解配置aop事务

<!-- 开启使用注解管理aop事务 -->
<tx:annotation-driven/>

注解配置过程如下:

4.5 ApplicationContext获取方式分析

  注解直接注入

@Autowired

private ApplicationContext applicationContext;

  实现 ApplicationContextAware 接口

  构造方法传入ApplicationContext

4.6 配置文件分析

1. 在注解中,针对一个类可以通过@Configuration注解在类上标识为配置文件,在类中通过@Bean注解注入bean

2. 基于配置文件的包扫描功能来扫描注解:<context:component-scan base-package="com.hw.spring" />;如下两种方式等价

4.7 ApplicationContext分析

web开发中使用applicationContext,在资源匮乏的环境可以使用BeanFactory。applicationContext的获取有3种方式

4.8  模块化配置

<import resource="/路径**/applicationContext.xml"/><!-- 引入其他applicationContext.xml下的配置 -->

5. 注解模式

上述方式User中注入Car时,建议通过构造函数注入,否则可能出现null,因为Java初始化顺序如下:

1. 静态变量/静态代码

2. 实例变量/初始化代码块

3. 构造方法

4. @Autowired

2. 构造函数注入

要想使用注解代替配置文件,需要在applicationContext.xml中配置如下:

<!-- 自动扫描包下类的注解 -->
<context:component-scan base-package="com.oxygen.bean"></context:component-scan>

然后包下所有类的注解都可以被spring扫描到,可以通过@Component、@Controller、@Service、@Repository等注解注入,以Student类为例,如下

package com.oxygen.bean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; /**
* @author Oxygen
* @date 2018年10月9日
*/
@Component//等价于@Component("user"),等价于<bean name="student" class="com.oxygen.bean.Student"></bean>
@Scope(scopeName="prototype")//多例
public class Student {
@Value("tom")//该方式通过反射Field赋值,破坏了封装性,此外也可以在setName()方法上赋值,结果是一样的
private String name;
@Value(value="18") //也可以是@Value("18"),注解只有一个值而且是value属性时,value属性可以省略
private Integer age; @Autowired //注解注入引用类型对象,会按照类型进行匹配,但是该注解有一个问题是,如果有多个Car类,则无法选择
//此时要配合@Qualifier("car2")使用来指定注入的类
//此外有一个更为简单的注解可以直接指定注入的类@Resource(name="car2")
private Car car; @PostConstruct//在Student对象被创建后调用,相当于init-method
public void init() {
System.out.println("init...");
} @PreDestroy //Student对象销毁之前调用,相当于destroy-method
public void destroy() {
System.out.println("destroy...");
}
}

6. 功能整合

6.1 Spring与Junit整合

1. 普通的单元测试如下:

@Test
public void fun1() {
// 1. 创建容器对象
// 2. 从容器中获取已经在配置文件中注入的user对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
print(1, user);
}
public static void print(Integer i, Object object) {
System.out.println(String.format("%d,%s", i, object.toString()));
}

注:如果在自定义的main方法中,获取applicaitonContext,方式如下:

1. 配置文件方式获取:ClassPathXmlApplicationContext contex = new ClassPathXmlApplicationContext("applicationContext.xml");

2. 注解获取:AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnotationScan.class);

2. Spring整合Junit单元测试如下:

@RunWith(SpringJUnit4ClassRunner.class) // 该注释会帮助我们创建容器
@ContextConfiguration("classpath:applicationContext.xml") // 读取配置文件
public class TestDemo{
@Resource(name = "user") //将user对象注入到属性u中
private User u; @Test
public void fun1() {
System.out.println(u);
}
}

6.2 Spring与JDBC整合

Spring提供了一个可以操作数据库的对象JDBCTemplateJDBC模板对象,该对象封装了JDBC技术,该对象与DBUtils中的QueryRunner相似

JDBC模板演示:

 package com.oxygen.jdbctemplate;

 import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper; import com.oxygen.bean.User; /**
* @author Oxygen
* @date 2018年10月11日
*/
public class UserDaoImpl implements UserDao { private JdbcTemplate jdbcTemplate; public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
} public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
} @Override
public void save(User user) { //增
String sql = "insert into t_user values(null,?)";
jdbcTemplate.update(sql, user.getName());
} @Override
public void delete(Integer id) { //删
String sql = "delete from t_user where id = ?";
jdbcTemplate.update(sql, id);
} @Override
public void update(User user) { //改
String sql = "update t_user set name = ? where id = ?";
jdbcTemplate.update(sql, user.getName(), user.getId());
} @Override
public User getById(Integer id) { //查
String sql = "select * from t_user where id = ?";
User user = jdbcTemplate.queryForObject(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int arg1) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
return user;
}
}, id);
return user;
} @Override
public int getTotalCount() { //
String sql = "select count(*) from t_user";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
return count;
} @Override
public List<User> getAll() {
String sql = "select * from t_user";
List<User> list = jdbcTemplate.query(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int arg1) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
return user;
}
});
return list;
} }

将Userdao交给Spring容器来管理,通过上述的代码可知UserDaoImpl依赖JdbcTemplate jdbcTemplate的,而JdbcTemplate依赖Datasource,因此在

application-Context.xm中配置如下:

<!-- 告知spring读取数据库配置文件 -->
<context:property-placeholder location="classpath:db.properties" /><!-- classpath*:properties/*.properties -->
<!-- 1. 将UserDao放入spring容器 -->
<bean name="userDao" class="com.oxygen.jdbctemplate.UserDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!-- 2. 将JDBCTemplate放入Spring容器 -->
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 3. 将连接池放入Spring容器 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="${jdbc.url}" /><!-- value从配置文件读取 -->
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="driverClassName" value="${jdbc.driver}" />
<property name="maxActive" value="10" />
<property name="minIdle" value="5" />
</bean>

显然上述配置方式过于繁琐,如果UserDaoImpl extends JDBCSupport的话,只要在XML文件中注入DataSource引用即可。

<bean id="student" class="com.huawei.domain.Student" init-method="initMethod" destroy-method="destroyMethod" lazy-init="true"/>

  

必须借助一个接口才能产生代理对象,所以在使用代理之前,先要有一个接口,然后定义一个类实现接口

连接点被动态代理拦截下来

【ssm】spring功能讲解的更多相关文章

  1. SSM(Spring + Springmvc + Mybatis)框架面试题

    JAVA SSM框架基础面试题https://blog.csdn.net/qq_39031310/article/details/83050192 SSM(Spring + Springmvc + M ...

  2. SSM(Spring +SpringMVC + Mybatis)框架搭建

    SSM(Spring +SpringMVC + Mybatis)框架的搭建 最近通过学习别人博客发表的SSM搭建Demo,尝试去搭建一个简单的SSMDemo---实现的功能是对用户增删改查的操作 参考 ...

  3. SSM(Spring,SpringMVC,Mybatis)框架整合项目

    快速上手SSM(Spring,SpringMVC,Mybatis)框架整合项目 环境要求: IDEA MySQL 8.0.25 Tomcat 9 Maven 3.6 数据库环境: 创建一个存放书籍数据 ...

  4. maven/eclipse搭建ssm(spring+spring mvc+mybatis)

    maven/eclipse搭建ssm(spring+spring mvc+mybatis) 前言 本文旨在利用maven搭建ssm环境,而关于maven的具体内容,大家可以去阅读<Maven 实 ...

  5. 电脑键盘上的F键有什么用 电脑F键功能讲解

    接触电脑这么多年了,F1到F12这几个键你真的会用吗?电脑键盘上的F键有什么用?你了解过吗?这里带来电脑F键功能讲解,一起来看看. F1:帮助 在程序里或者资源管理器界面,按F1会弹出帮助按钮. F2 ...

  6. SSM Spring+SpringMVC+mybatis+maven+mysql环境搭建

    SSM Spring+SpringMVC+mybatis+maven环境搭建 1.首先右键点击项目区空白处,选择new->other..在弹出框中输入maven,选择Maven Project. ...

  7. Java安全(权限)框架 - Shiro 功能讲解 架构分析

    Java安全(权限)框架 - Shiro 功能讲解 架构分析 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 简述Shiro Shiro出自公司Apache(阿帕奇),是java的一 ...

  8. SSM(Spring+SpringMVC+Mybatis)框架环境搭建(整合步骤)(一)

    1. 前言 最近在写毕设过程中,重新梳理了一遍SSM框架,特此记录一下. 附上源码:https://gitee.com/niceyoo/jeenotes-ssm 2. 概述 在写代码之前我们先了解一下 ...

  9. Navicat Premium 常用功能讲解

    https://www.linuxidc.com/Linux/2016-04/130159.htm Navicat Premium 常用功能讲解 1.快捷键 1.1. F8 快速回到当前对象列表 1. ...

随机推荐

  1. how to modify vs2017

    https://docs.microsoft.com/en-us/visualstudio/install/modify-visual-studio 直接用everything搜索vs_install ...

  2. POJ 1060:Modular multiplication of polynomials

    Modular multiplication of polynomials Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4 ...

  3. tflearn 保存模型重新训练

    from:https://stackoverflow.com/questions/41616292/how-to-load-and-retrain-tflean-model This is to cr ...

  4. [Codeforces 460C] Present

    [题目链接] https://codeforces.com/contest/460/problem/C [算法] 二分 + 贪心 要求最小值最大 , 我们不妨二分最小值 , 若一盆花的高度小于二分的值 ...

  5. Spark SVM分类器

    package Spark_MLlib import java.util.Properties import org.apache.spark.mllib.regression.LabeledPoin ...

  6. 10.11 NOIP模拟题(1)

    /* 离散化 差分 */ #include<bits/stdc++.h> #define N 4000007 using namespace std; int n,ans; int tmp ...

  7. bzoj4987: Tree(树形dp)

    Description 从前有棵树. 找出K个点A1,A2,…,Ak. 使得∑dis(AiAi+1),(1<=i<=K-1)最小.   Input 第一行两个正整数n,k,表示数的顶点数和 ...

  8. [App Store Connect帮助]四、添加 App 图标、App 预览和屏幕快照(1)App Store 图标、App 预览和屏幕快照概述

    您可以为您的 App Store 产品页提供有关您 App 的 App Store 图标.三个 App 预览和十张屏幕快照. App Store 图标 您必须提供一个 App Store 图标,用于在 ...

  9. N - Binomial Showdown (组合数学)

    Description In how many ways can you choose k elements out of n elements, not taking order into acco ...

  10. 解决前后端分离的“两次请求”引出的Web服务器跨域请求访问问题的解决方案

    在前后端分离的项目中,前端和后端可能是在不同的服务器上,也可以是Docker上,那就意味着前端请求后端Restful接口时,存在跨域情况. 后端在做了通用的跨域资源共享CORS设置后,前端在做ajax ...