简介
Spring : 春天 —>给软件行业带来了春天
2002年,Rod Jahnson首次推出了Spring框架雏形interface21框架。
2004年3月24日,Spring框架以interface21框架为基础,经过重新设计,发布了1.0正式版。
很难想象Rod Johnson的学历 , 他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。
Spring理念 : 使现有技术更加实用 . 本身就是一个大杂烩 , 整合现有的框架技术
- 是一个轻量级的企业级应用框架
- 企业应用开发的”一站式”选择,贯穿于表现层、业务层、持久层
-
优点
- 低侵入式设计
- 独立于各种应用服务器
- 依赖注入特性将组件关系透明化,降低耦合度
- 面向切面编程特性允许将通用任务进行集中式处理
- 与第三方框架的良好整合
Spring体系结构
Spring两大核心机制
- IOC:工厂模式
- AOP:代理模式
一,如何使用IOC
- 在创建maven工程,在pom.xml中导入相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xinxi2</groupId>
<artifactId>xinxi2-maven01</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.version>5.2.5.RELEASE</spring.version>
</properties>
<dependencies>
<!-- mysql 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<!-- mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>
- 创建一个墨盒实体类
package com.xinxi2.printor;
public class Printor {
private MoHe moHe; // 墨盒
private Paper paper; // 纸
// 目标对象
public void print(){
moHe.MoHe();
paper.Print();
}
public MoHe getMoHe() {
return moHe;
}
public void setMoHe(MoHe moHe) {
this.moHe = moHe;
}
public Paper getPaper() {
return paper;
}
public void setPaper(Paper paper) {
this.paper = paper;
}
}
- 创建一个墨盒接口
package com.xinxi2.printor;
public interface MoHe {
void MoHe();
}
- 创建一个纸接口
package com.xinxi2.printor;
public interface Paper {
void Print();
}
- 创建一个类实现墨盒接口,重写墨盒方法,输出彩色墨盒
package com.xinxi2.printor;
public class ColorMoHelmpl implements MoHe{
@Override
public void MoHe() {
System.out.println("彩色墨盒");
}
}
- 创建一个类实现墨盒接口,重写墨盒方法,输出黑色墨盒
package com.xinxi2.printor;
public class BlackMoHelmpl implements MoHe{
@Override
public void MoHe() {
System.out.println("黑白墨盒");
}
}
- 创建一个类实现纸接口,重写纸方法,输出A4纸
package com.xinxi2.printor;
public class A4paperlmpl implements Paper{
@Override
public void Print() {
System.out.println("A4纸");
}
}
- 在resources路径下创建applicationContext.xml配置文件
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<bean id="mohe1" class="com.xinxi2.printor.BlackMoHelmpl"></bean>
<bean id="A4paperimpl" class="com.xinxi2.printor.A4paperlmpl"></bean>
<bean id="printor" class="com.xinxi2.printor.Printor">
<property name="moHe" ref="mohe1"></property>
<property name="paper" ref="A4paperimpl"></property>
</bean>
</beans>
- 调用API,从IOC获取对象
@Test
public void test02(){
// 获取springContext上下文对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Printor printor = (Printor)ac.getBean("printor");
printor.print();
}
-
输出结果
二,AOP
- AOP目标
- 让我们专注于业务功能处理
- AOP原理
- 将复杂的需求分解出不同方面,将不同对象、不同模块之间的共同业务集中解决
-
通过动态代理的方式,把抽离出来的共性代码”织入”到业务代码中,实现对原有代码的增强处理
如图
- AOP相关术语
- Aspect(切面)
- Advice(增强处理)
- Pointcut(切入点)
- Join Point(连接点)
- Target Object(目标对象)
- AOP proxy(AOP 代理)
- Weaving(织入)
定义切入点
切入点:简单来说,就是连接点的查询条件
<aop:config>
<aop:pointcut id="loggerPointcut"
expression="execution(public void print(..))"/>
<aop:aspect ref="sysLogger">
</aop:aspect>
</aop:config>
表达式匹配规则举例
expression="execution(public void print(..))"/>
- 各种增强
增强类型 | 特点 |
---|---|
Before | 前置增强处理,在目标方法前织入增强处理 |
AfterReturning | 后置增强处理,在目标方法正常执行(不出现异常)后织入增强处理 |
AfterThrowing | 异常增强处理,在目标方法抛出异常后织入增强处理 |
After | 最终增强处理,不论方法是否抛出异常,都会在目标方法最后织入增强处理 |
Around | 环绕增强处理,在目标方法的前后都可以织入增强处理。可以控制目标方法是否执行 |
织入增强处理
织入:在切入点插入增强处理
- 演示:创建实体类添加增强方法
package com.xinxi2.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component()
public class LoggerAdvic {
@Before("execution(public void wprk())")
public void before(JoinPoint jp){
System.out.println("前缀增强");
}
@AfterReturning("execution(public void wprk())")
public void retuRning(JoinPoint jp){
System.out.println("后置增强");
}
@AfterThrowing("execution(public void wprk())")
public void afterException(JoinPoint jp){
System.out.println("异常增强");
}
@Around("execution(public void wprk())")
public Object around(ProceedingJoinPoint pjp){
Object result = null;
try {
System.out.println("--------------------");
result = pjp.proceed(); // 执行方法
System.out.println("********************");
}catch (Throwable e){
e.printStackTrace();
}
System.out.println("环绕增强");
return result;
}
@After("execution(public void wprk())")
public void after(JoinPoint jp){
System.out.println("最终增强");
}
}
- 在applicationContext.xml中写aop:config标签
<aop:config>
<aop:pointcut id="loggerPointcut"
expression="execution(public void print(..))"/>
<aop:aspect ref="sysLogger">
<aop:before method="beforeLogger" pointcut-ref="loggerPointcut"></aop:before>
<aop:after-returning method="afterReturning" pointcut-ref="loggerPointcut" returning="obj"></aop:after-returning>
<aop:after-throwing method="afterException" pointcut-ref="loggerPointcut" throwing="e"></aop:after-throwing>
<aop:around method="around" pointcut-ref="loggerPointcut" ></aop:around>
<aop:after method="after" pointcut-ref="loggerPointcut"></aop:after>
</aop:aspect>
</aop:config>
解释以上几种增强方法
异常抛出增强
-
特点
- 在目标对象方法抛出异常时织入增强处理
- 可灵活拔插的异常处理方案
<aop:config>
<aop:pointcut id="loggerPointcut"
expression="execution(public void print(..))"/>
<aop:aspect ref="sysLogger">
<!-- 异常增强 -->
<aop:after-throwing method="afterException" pointcut-ref="loggerPointcut" throwing="e"></aop:after-throwing>
</aop:aspect>
</aop:config>
最终增强
-
特点
- 无论方法正常运行还是抛出异常,都会在目标方法最后织入增强处理,即:该增强都会得到执行
- 与Java中finally代码块的作用相似,通常用于释放资源
- 可灵活拔插
<aop:config>
<aop:pointcut id="loggerPointcut"
expression="execution(public void print(..))"/>
<aop:aspect ref="sysLogger">
<!-- 最终增强 -->
<aop:after method="after" pointcut-ref="loggerPointcut"></aop:after>
</aop:aspect>
</aop:config>
环绕增强
-
特点
- 目标方法前后都可织入增强处理
- 可获取或修改目标方法的参数、返回值
- 可对目标方法进行异常处理,甚至可以决定目标方法是否执行
<aop:config>
<aop:pointcut id="loggerPointcut"
expression="execution(public void print(..))"/>
<aop:aspect ref="sysLogger">
<!-- 环绕增强 -->
<aop:around method="around" pointcut-ref="loggerPointcut" ></aop:around>
</aop:aspect>
</aop:config>
构造注入
-
可以使用带参构造
- Spring通过构造方法为属性赋值的一种注入方式
- 可以在对象初始化时对属性赋值,具有良好的时效性
<bean id="daodao" class="com.xinxi2.bean.TSysUser">
<constructor-arg name="acccunt" value="王某某"></constructor-arg>
<constructor-arg name="address" value="王某"></constructor-arg>
</bean>
P命名的注入
使用属性而不是子元素的形式配置Bean的属性
<bean id="唯一标识" class="类的全路径"
p:"属性1"="注入的值" p:"属性2"="注入的值" />
<bean id="唯一标识" class="类的全路径"
p:属性-ref="注入的Bean" />
配置文件中使用p命名空间时,需要先添加p命名空间的声明
xmlns:p=“http://www.springframework.org/schema/p”
三,Spring表单标签
3.1,Spring常用表单标签
名称 | 说明 |
fm:form/ | 渲染表单元素 |
fm:input/ | 输入框组件标签 |
fm:password/ | 密码框组件标签 |
fm:hidden/ | 隐藏框组件标签 |
fm:textarea/ | 多行输入框组件标签 |
fm:radiobutton/ | 单选框组件标签 |
fm:checkbox/ | 复选框组件标签 |
fm:select/ | 下拉列表组件标签 |
fm:error/ | 显示表单数据校验对应的错误信息 |
fm:form标签
-
modelAttribute
指定绑定的模型属性
若不指定该属性,默认从模型中尝试获取名为”command”的表单属性,建议指定该属性 -
action
指定表单提交的目标URL
可不指定,则自动以获取表单页面的URL为目标进行提交,可以通过不同请求方式区分不同操作 -
method
GET
POST
3.2,标签属性
属性 | 描述 |
path | 属性路径,表示表单对象属性,如account、realName等 |
cssClass | 表单组件对应的CSS样式类名 |
cssErrorClass | 当提交表单后报错(服务端错误),采用的CSS样式类 |
cssStyle | 表单组件对应的CSS样式 |
htmlEscape | 绑定的表单属性值是否要对HTML特殊字符进行转换,默认为true |
3.3,数据校验
JSR 303 约束
约束 | 说明 |
@Null | 被注释的元素必须为null |
@NotNull | 被注释的元素必须不为null |
@AssertTrue | 被注释的元素必须为true |
@AssertFalse | 被注释的元素必须为false |
@Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@DecimalMin(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@DecimalMax(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@Size(max,min) | 被注释的元素的大小必须在指定的范围内 |
@Digits(integer,fraction) | 被注释的元素必须是一个数字,其值必须在可接受的范围内 |
@Past | 被注释的元素必须是一个过去的日期 |
@Future | 被注释的元素必须是一个将来的日期 |
@Pattern(value) | 被注释的元素必须符合指定的正则表达式 |