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. Oracle数据库查询锁表及解锁

    一.查询哪些表被锁以及查看锁表得会话及操作系统进程ID 其中locked_mode为锁的级别,spid为数据库所在操作系统的进程id select c.sid, c.serial#, c.userna ...

  2. 最新Ceph L版与openstack Pike对接

    安装Ceph luminous   实验环境 三台服务器,每台服务器都有4块硬盘,每台服务器都将自己的第一块硬盘作为系统盘,剩下的做ceph   一.在所有服务器上操作 #使用阿里源 yum inst ...

  3. 浅谈OSI参考模型(七层模型)

    很多人说"21世纪人类最伟大的发明就是计算机":正是如此,21世纪的今天,计算机正对我们的社会发展和生活起居产生着不可估量的影响:电脑,手机都能上网随时随地了解多彩的世界.但是有时 ...

  4. DEDECMS:将dedecms系统的data目录迁移到web以外目录

    dedecms系统的data目录是系统缓存和配置文件的目录,一般都有可以读写的权限,只要是能够写入的目录都可能存在安全隐患,很多站长甚至给予这个目录可执行的权限,更是非常危险,所以我们建议将这个dat ...

  5. nginx教程<一>

    2020最新Nginx教程全面讲解教程,感觉讲的很不错但是需要有docker基础,因为是基于docker快速搭建的nginx. 1.为什么要学习Nginx 肯定是工作和业务需求催生的学习需要哈哈,不过 ...

  6. 深入理解nodejs的HTTP处理流程

    目录 简介 使用nodejs创建HTTP服务 解构request 处理Request Body 处理异常 解构response 简介 我们已经知道如何使用nodejs搭建一个HTTP服务,今天我们会详 ...

  7. 如何学习Java?从标识符开始

    标识符 1.定义 Java对各种变量.方法和类等要素命名时使用的字符序列称为标识符(包含但不限于:类名.变量名.方法名.接口名.包名--) 2.命名规则 1.由26个英文字母大小写,0-9,_或$组成 ...

  8. Codeforces Round #626 Div2 D. Present(位掩码,二分)

    题目链接:https://codeforces.com/contest/1323/problem/D 题意:给了大小为4e5的数组a,其中1<=ai<=1e7.求所有点对和的异或和,即: ...

  9. Codeforces Round #657 (Div. 2) C. Choosing flowers(贪心)

    题目链接:https://codeforces.com/contest/1379/problem/C 题意 有 $m$ 种花,每种花数量无限,第一次购买一种花收益为 $a_i$,之后每一次购买收益为 ...

  10. 【noi 2.6_90】滑雪(DP)

    题意:输出最长下降路径的长度. 解法:f[i][j]表示结尾于(i,j)的最长的长度.由于无法确定4个方位已修改到最佳,所以用递归实现. 1 #include<cstdio> 2 #inc ...