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. hadoop(集群)完全分布式环境搭建

    一,环境 主节点一台: ubuntu desktop 16.04 zhoujun      172.16.12.1 从节点(slave)两台:ubuntu server 16.04 hadoop2  ...

  2. HarmonyOS三方件开发指南(8)——RoundedImage

    [小年答谢,新春送礼]免费抽取1000元京东卡+更多新春好礼~查看详情>>> 目录: 1. RoundedImage组件功能介绍 2. RoundedImage使用方法 3. Rou ...

  3. Word 脚本 (自用)

    打开开发工具 右击功能区->自定义功能区 勾选开发工具->确定 导入代码 开发工具选项卡->Visual Basic 右击Normal->插入->模块 粘贴代码-> ...

  4. HDU -1151 二分匹配与有向无环图不相交最小路径覆盖数

    题意: 考虑一个小镇,那里的所有街道都是单向的,并且每条街道都从一个路口通往另一个路口.还众所周知,从一个十字路口开始,穿过城镇的街道,您将永远无法到达同一十字路口,即,城镇的街道没有环. 基于这些假 ...

  5. Warm up HDU - 4612 树的直径

    题意:给出n个点和m条边的无向图,存在重边,问加一条边以后,剩下的桥的数量最少为多少. 题解: 你把这个无向图缩点后会得到一个只由桥来连接的图(可以说这个图中的所有边都是桥,相当于一棵树),然后我们只 ...

  6. Kubernetes部署Prometheus+Grafana(非存储持久化方式部署)

    1.在master节点处新建一个文件夹,用于保存下载prometheus+granfana的yaml文件 mkdir /root/prometheus cd /root/prometheus git ...

  7. 1009E Intercity Travelling 【数学期望】

    题目:戳这里 题意:从0走到n,难度分别为a1~an,可以在任何地方休息,每次休息难度将重置为a1开始.求总难度的数学期望. 解题思路: 跟这题很像,利用期望的可加性,我们分析每个位置的状态,不管怎么 ...

  8. mysql+python+pymysql的一些细节问题

    报错 (1044, "Access denied for user 'erio'@'localhost' to database 'library'") 就是权限问题了,没什么好说 ...

  9. codeforces 1042C Array Product【构造】

    题目:戳这里 题意:n个数,两种操作,第一种是a[i]*a[j],删掉a[i],第一种是直接删除a[i](只能用一次)剩下的数序列号不变.操作n-1次,使最后剩下的那个数最大化. 解题思路: 正数之间 ...

  10. codeforces 1036B - Diagonal Walking v.2【思维+构造】

    题目:戳这里 题意:起点(0,0),终点(n,m),走k步,可以走8个方向,问能不能走到,能走到的话最多能走多少个斜步. 解题思路:起点是固定的,我们主要分析终点.题目要求走最多的斜步,斜步很明显有一 ...