Spring5 框架概述

1、Spring 是轻量级的开源的 JavaEE 框架

2、Spring 可以解决企业应用开发的复杂性

3、Spring 有两个核心部分:IOC 和 Aop

(1)IOC:控制反转,把创建对象过程交给 Spring 进行管理

(2)Aop:面向切面,不修改源代码进行功能增强

4、Spring 特点

(1)方便解耦,简化开发

(2)Aop 编程支持

(3)方便程序测试

(4)方便和其他框架进行整合

(5)方便进行事务操作

(6)降低 API 开发难度

IOC 控制反转

1、什么是 IOC

(1)控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理

(2)使用 IOC 目的:为了耦合度降低

(3)做入门案例就是 IOC 实现

2、IOC 底层原理

(1)xml 解析、工厂模式、反射

IOC(BeanFactory 接口)

1、IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂

2、Spring 提供 IOC 容器实现两种方式:(两个接口)

(1)BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象

(2)ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人员进行使用加载配置文件时候就会把在配置文件对象进行创建

3、ApplicationContext 接口有实现类

IOC 操作 Bean 管理(xml 方式)

1、什么是 Bean 管理

(0)Bean 管理指的是两个操作

(1)Spring 创建对象

(2)Spirng 注入属性

2、Bean 管理操作有两种方式

(1)基于 xml 配置文件方式实现

(2)基于注解方式实现

创建对象、属性注入
setter属性注入
<bean id="user" class="cn.yang.User">
<property name="name" value="周杰伦"></property>
<property name="id" value="123123"></property>
</bean> 使用有参构造注入
<bean id="user" class="cn.yang.User">
<constructor-arg name="id" value="123"></constructor-arg>
<constructor-arg name="name" value="周杰伦"></constructor-arg>
</bean> p名称空间注入
xmlns:p="http://www.springframework.org/schema/p"
<bean id="user" class="cn.yang.User" p:id="1234" p:name="jack"></bean>
注入外部bean和内部bean
级联赋值

可通过外部bean和内部bean两种方式实现

外部bean:创建dao组件,在service中注入dao
<bean name="userDaoImpl" class="cn.yang.dao.UserDaoImpl"></bean>
<bean name="userServiceImpl" class="cn.yang.service.UserServiceImpl">
<property name="userDao" ref="userDaoImpl"></property>
</bean> 内部bean:
<bean name="emp" class="cn.yang.bean.Emp">
<property name="name" value="jack"></property>
<property name="gender" value="男"></property>
<property name="dept">
<bean name="dept" class="cn.yang.bean.Dept">
<property name="dname" value="人事部"></property>
</bean>
</property>
</bean>
注入集合属性
<bean name="stu" class="cn.yang.Stu">
<property name="courses">
<array>
<value>语文</value>
<value>数学</value>
<value>英语</value>
<value>品德</value>
</array>
</property>
<property name="list">
<list>
<value>1..</value>
<value>2..</value>
<value>3..</value>
</list>
</property>
<property name="maps">
<map>
<entry key="aaa" value="AAA"></entry>
<entry key="bbb" value="BBB"></entry>
<entry key="ccc" value="CCC"></entry>
</map>
</property>
<property name="cs">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean> <bean name="course1" class="cn.yang.Course">
<property name="name" value="JAVA"></property>
</bean> <bean name="course2" class="cn.yang.Course">
<property name="name" value="C++"></property>
</bean>
可提取后注入
引入:
xmlns:util="http://www.springframework.org/schema/util"
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd <util:list id="list">
<value>JAVA</value>
<value>Spring</value>
<value>Mybatis</value>
</util:list> <bean id="book" class="cn.yang.Book">
<property name="bnames" ref="list"></property>
</bean>
常用字面量
<bean id="user" class="cn.yang.User">
<property name="name" value="周杰伦"></property>
<property name="id">
<!--null值-->
<null/>
</property>
<property name="address">
<!--特殊符号 <![CDATA[。。。。]]>-->
<value><![CDATA[ <<台湾>> ]]></value>
</property>
</bean>

bean 的性质

  1. Spring 有两种 bean,普通 bean, 工厂 bean(FactoryBean)

  2. 普通 bean:配置文件中定义 bean 类型就是返回类型

  3. 工厂 bean:返回类型可以与配置文件中定义的不一样

    1. 创建类,实现接口 FactoryBean

    2. 实现接口里的方法,在实现的方法中定义返回的 bean 类型

    3. 实现

      public class MyBean implements FactoryBean<Course> {
      @Override
      public Course getObject() throws Exception {
      Course c = new Course();
      c.setName("abc");
      return c;
      }
      } <bean id="myBean" class="cn.yang.MyBean"></bean>
  4. bean 作用域

    1. 设置创建 bean 实例是单实例还是多实例

    2. 默认:singleton 单实例,加载配置文件时创建

    3. 设置多实例 prototype,调用时创建

      <bean scope="prototype"></bean>
  5. bean 生命周期

    (1)通过构造器创建 bean 实例(无参数构造)

    (2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)

    (3-)把 bean 实例传递 bean 后置处理器的方法postProcessBeforeInitialization

    (3)调用 bean 的初始化的方法(需要进行配置初始化的方法)

    (3+)把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization

    (4)bean 可以使用了(对象获取到了)

    (5)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)

    public class Order {
    private String name; public Order() {
    System.out.println("step1 construct function");
    } public void setName(String name) {
    this.name = name;
    System.out.println("step2 setter function");
    } public void initMethod() {
    System.out.println("step3 init method");
    }
    public void destroyMethod() {
    System.out.println("step5 destroy method");
    }
    }
    <bean id="order" class="cn.yang.Order" init-method="initMethod" destroy-method="destroyMethod">
    <property name="name" value="order"></property>
    </bean>
    后置处理器,实现接口 BeanPostProcessor
    <bean id="myPost" class="cn.yang.MyPost"></bean>

自动装配

  1. 根据属性名称自动注入 autowire="byName"

    <bean id="emp" class="cn.yang.Emp" autowire="byName" scope="prototype"></bean>
    <bean id="dept" class="cn.yang.Dept"></bean>
  2. 根据属性类型自动装配 autowire="byType"

    <bean id="emp" class="cn.yang.Emp" autowire="byType" scope="prototype"></bean>
    <bean id="dept" class="cn.yang.Dept"></bean>

外部属性文件

以配置druid连接池为例

  1. 直接配置

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="..."></property> 非必要,可根据url自动导入
    <property name="url" value="..."></property>
    <property name="username" value="..."></property>
    <property name="password" value="..."></property>
    </bean>
  2. 引入外部属性文件

    prop.driverClass=com.mysql.jdbc.Driver
    prop.url=jdbc:mysql://127.0.0.1/test
    prop.user=root
    prop.pass=root
    先引入context
    xmlns:context="http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd <context:property-placeholder location="classpath:mysql.properties" /> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${prop.driverClass}"></property>
    <property name="url" value="${prop.url}"></property>
    <property name="username" value="${prop.user}"></property>
    <property name="password" value="${prop.pass}"></property>
    </bean>

IOC 操作 Bean 管理(注解方式)

Bean 管理中创建实例的注解
  • @Component
  • @Service
  • @Controller
  • @Repository
注解方式创建实例
  1. 配置文件中开启组件扫描

    <!--配置包扫描  使用默认过滤器-->
    <con:component-scan base-package="cn.yang"/>
  2. 在类上添加注解

    @Component(value="userService")
    public class UserService {
    public void add() {
    System.out.println("userService add...");
    }
    }
  3. 细节配置

    <!--配置 1 只扫描带Controller注解的类-->
    <context:component-scan base-package="cn.yang">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan> <!--配置 2 不扫描带Controller注解的类-->
    <context:component-scan base-package="cn.yang">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
  4. 使用注解注入属性

    1. @Autowired 根据属性自动装配

      @Service
      public class UserService {
      @Autowired
      private UserDao userDao;
      }
    2. @Qualifier 根据名称注入

      @Service
      public class UserService {
      @Qualifier(value = "userDaoImpl")
      private UserDao userDao;
      }
    3. @Resource 根据类型和名称注入

    4. @Value 注入普通属性

完全注解开发
  1. 创建配置类,替代 xml 配置文件

    @Configuration
    @ComponentScan(basePackages = "cn.yang")
    public class SpringConfig {
    }
  2. 编写测试类

    @Test
    public void test2() {
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    UserService userService = context.getBean("userService", UserService.class);
    userService.add(); }

AOP 面向切面

概念

  1. 面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
  2. 通俗描述:不通过修改源代码方式,在主干功能里面添加新功能

底层原理

  1. 使用 JDK 动态代理
  2. 使用 CGLIB 动态代理

AOP 术语

  1. 连接点:类中可以被增强的方法
  2. 切入点:实际增强的方法
  3. 通知:实际增强的逻辑部分,分为前置、后置、环绕、异常、最终通知
  4. 切面:把通知应用到切入点的过程

AOP 操作(注解)

引入 AspectJ 依赖

切入点表达式

execution( [权限修饰符] [返回类型] [类全路径] [方法名称] ([参数列表]) )

xmlns:aop="http://www.springframework.org/schema/aop"

<aop:config>
<aop:pointcut id="point" expression="execution(* cn.yang.bean.Book.buy(..))"/>
<aop:aspect ref="bookProxy">
<aop:before method="before" pointcut-ref="point"></aop:before>
</aop:aspect>
</aop:config>

操作

1. 创建类
@Component
public class User {
public void add() {
System.out.println("add...");
}
}
2. 创建增强类
@Component
@Aspect //生成代理对象
@Order(2) //优先级
public class UserProxy {
}
3. 开启代理对象
<!--开启aspect生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> <!--配置包扫描 使用默认过滤器-->
<con:component-scan base-package="cn.yang"/>
4. 配置通知

@Component
@Aspect
@Order(2)
public class UserProxy { @Before(value = "execution(* cn.yang.bean.User.add(..))")
public void before() {
System.out.println("before...");
} @After(value = "execution(* cn.yang.bean.User.add(..))")
public void after() {
System.out.println("after...");
} @AfterReturning(value = "execution(* cn.yang.bean.User.add(..))")
public void afterReturning() {
System.out.println("after returning");
} @AfterThrowing(value = "execution(* cn.yang.bean.User.add(..))")
public void afterThrowing() {
System.out.println("after throwing");
} @Around(value = "execution(* cn.yang.bean.User.add(..))")
public void afterThrowing(ProceedingJoinPoint pj) throws Throwable{
System.out.println("around-");
pj.proceed();
System.out.println("around+");
}
}
5. 相同的切入点抽取
//抽取公共切入点
@Pointcut("execution(* cn.yang.bean.User.add(..))")
public void point() {
}
6.设置增强类优先级

有多个增强类对同一个方法增强,设置增强类优先级

@Order(1)
7. 完全使用注解开发
@Configuration
@ComponentScan(basePackages = {"cn.yang"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {}

AOP 操作 ( xml )

xmlns:aop="http://www.springframework.org/schema/aop

创建实例
<bean id="book" class="cn.yang.bean.Book"></bean>
<bean id="bookProxy" class="cn.yang.bean.BookProxy"></bean> 配置aop
<aop:config>
<!--配置切入点-->
<aop:pointcut id="point" expression="execution(* cn.yang.bean.Book.buy(..))"/>
<!--配置切面-->
<aop:aspect ref="bookProxy">
<!--增强作用在具体的方法上-->
<aop:before method="before" pointcut-ref="point"></aop:before>
</aop:aspect>
</aop:config>

JdbcTemplate

Spring 框架对 JDBC 进行封装,简化对数据库的操作

1. 引入依赖

2. 配置数据库连接池

<context:property-placeholder location="classpath:mysql.properties" />

<context:property-placeholder location="classpath:mysql.properties" />

<!--2 配置数据库连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.user}"></property>
<property name="password" value="${prop.pass}"></property>
</bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--3 注入 dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean> <!--开启组件扫描-->
<context:component-scan base-package="cn.yang"></context:component-scan> mysql.properties
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://127.0.0.1/test
prop.user=root
prop.pass=root

3. 配置JdbcTemplate,注入DataSource

4. 创建dao,注入jdbcTemplate

5. CRUD 操作

@Repository
public class BookDaoImpl implements BookDao{ @Autowired
private JdbcTemplate jdbcTemplate; @Override
public void add(Book book) {
Object[] objs = {book.getName(),book.getId()};
String sql = "insert into book values(?,?)";
int update = jdbcTemplate.update(sql, objs);
System.out.println(update);
} @Override
public int queryCount() {
String sql = "select count(*) from book";
return jdbcTemplate.queryForObject(sql, Integer.class);
} @Override
public List<Book> findAll() {
String sql = "select * from book";
List<Book> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));
return query;
} @Override
public void batchAdd(List<Object[]> args) {
String sql = "insert into book values (?,?)";
int[] ints = jdbcTemplate.batchUpdate(sql, args);
System.out.println(Arrays.toString(ints));
} @Override
public void batchUpdate(List<Object[]> args) {
String sql = "update book set name=? where id=?";
int[] ints = jdbcTemplate.batchUpdate(sql, args);
System.out.println(Arrays.toString(ints));
} @Override
public void batchDel(List<Object[]> args) {
String sql = "delete from book where id=?";
int[] ints = jdbcTemplate.batchUpdate(sql, args);
System.out.println(Arrays.toString(ints));
} @Override
public void update(Book book) {
Object[] objs = {book.getName(),book.getId()};
String sql = "update book set name=? where id=?";
int update = jdbcTemplate.update(sql, objs);
System.out.println(update);
} @Override
public void del(String id) {
String sql = "delete from book where id=?";
int update = jdbcTemplate.update(sql, id);
System.out.println(update);
}
}

事务操作

事务的特性(ACID):原子性、一致性、隔离性、持久性

Spring 可通过 AOP 实现事务,通常在 service 层

  1. 在 spring 配置文件中配置事务管理器
  2. 在 spring 配置文件中开启事务注解
  3. 在 service 类上(或方法上)添加事务注解
<!--1 配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <!--2 开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
@Service
@Transactional //可配置事务相关参数
public class UserService {}

事务传播行为 propagation

事务隔离级别 ioslation

基于 xml 的事务操作

<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <!--配置通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="transform" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice> <!--配置切入点和切面-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pt" expression="execution(* cn.yang.service.UserService.*(..))"/>
<!--配置切面-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
</aop:config>

基于 注解 的事务操作

@Configuration
@ComponentScan(basePackages = "cn.yang")
@EnableTransactionManagement
public class MyConfig {
// 创建数据库连接池
@Bean
public DruidDataSource getDruidDatasource() {
DruidDataSource ds = new DruidDataSource();
ds.setUrl("jdbc:mysql://127.0.0.1/test");
ds.setUsername("root");
ds.setPassword("root");
return ds;
} // 创建JdbcTemplate 传入dataSource
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
} // 创建事务管理器
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
} }

spring5学习笔记的更多相关文章

  1. Spring5框架学习笔记

    Spring5学习笔记 介绍: 1.引入相应jar包 导入: ps:网上下载教程: https://repo.spring.io/release/org/springframework/spring/ ...

  2. 【转载】Java学习笔记

    转载:博主主页 博主的其他笔记汇总 : 学习数据结构与算法,学习笔记会持续更新: <恋上数据结构与算法> 学习Java虚拟机,学习笔记会持续更新: <Java虚拟机> 学习Ja ...

  3. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  4. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  5. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  6. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  7. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  8. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  9. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

随机推荐

  1. Mapper查询技巧

    Sql字段动态比较判断 <sql id="getUserInfoList_body"> SELECT * from userinfo <dynamic prepe ...

  2. (十八)整合Nacos组件,环境搭建和入门案例详解

    整合Nacos组件,环境搭建和入门案例详解 1.Nacos基础简介 1.1 关键特性 1.2 专业术语解释 1.3 Nacos生态圈 2.SpringBoot整合Nacos 2.1 新建配置 2.2 ...

  3. js部分知识整理,google浏览器的代码调试

    整理一些学过的js知识点,包括js中3个括号的含义,this的使用,递归,google浏览器的代码调试.Location的属性及常用方法,window对象常用方法,open方法等. js括号 在js中 ...

  4. Web程序设计基础期末大作业——模仿QQ飞车手游S联赛官网编写的网页

    QQ飞车手游是我非常喜欢的游戏,也是我现在为数不多的常在玩的游戏,刚好我Web程序设计基础的大作业是要做一套网站,我就借此机会模仿飞车S联赛官网的页面自己做了一个网页,又加了一些自己的元素,由于我做这 ...

  5. PAT(乙级)2020年春季考试

    比赛链接:https://pintia.cn/market/item/1287964475579875328 7-1 对称日 题解 模拟,注意年月日不足位在前面补零. 代码 #include < ...

  6. Codeforces Round #637 (Div. 2)

    比赛链接:https://codeforces.com/contest/1341 A - Nastya and Rice 题意 有 n 堆米,每堆质量在 [a-b,a+b] 之间,这些米的总质量是否可 ...

  7. ACM#学习心得0

    加入实验室也有些日子了,这是第一个近来的小小学习心得 1.在之前的训练题和考核题以及平时刷过的题中,我发现自己对字符串这一块的基础知识掌握还是比较差的,总是不能正确的接收的字符或字符串. 这两个星期, ...

  8. 大数据开发-Spark Join原理详解

    数据分析中将两个数据集进行 Join 操作是很常见的场景.在 Spark 的物理计划阶段,Spark 的 Join Selection 类会根 据 Join hints 策略.Join 表的大小. J ...

  9. 关于TCP状态TIME_WAIT的理解

    1.TIME_WAIT的作用: TIME_WAIT状态存在的理由:1)可靠地实现TCP全双工连接的终止 在进行关闭连接四次挥手协议时,最后的ACK是由主动关闭端发出的,如果这个最终的ACK丢失,服务器 ...

  10. Java解决Hash(散列)冲突的四种方法--开放地址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区

    最近时间有点紧,暂时先放参考链接了,待有时间在总结一下: 查了好多,这几篇博客写的真心好,互有优缺点,大家一个一个看就会明白了: 参考 1. 先看这个明白拉链法(链地址法),这个带源码,很好看懂,只不 ...