IOC

Sprint 配置的两种基本注入属性方法

依赖 bean 对象中的 set 方法进行属性的注入:

1
2
3
4
<bean id="book" class="pers.uang.pojo.Book">
<property name="name" value="人间失格"></property>
<property name="author" value="太宰治"></property>
</bean>

依赖 bean 对象的有参构造器进行属性的注入:

1
2
3
4
<bean id="book" class="pers.uang.pojo.Book">
<constructor-arg name="name" value="人间失格"></constructor-arg>
<constructor-arg name="author" value="太宰治"></constructor-arg>
</bean>

construtor-arg 中还有 index 属性,可用通过索引来对构造器中对应位置上的参数进行属性注入:

1
2
3
4
<bean id="book" class="pers.uang.pojo.Book">
<constructor-arg name="0" value="人间失格"></constructor-arg>
<constructor-arg name="1" value="太宰治"></constructor-arg>
</bean>

p 名称空间注入(了解)

首先添加在配置文件中 beans 标签添加 xmlns:p = "http://www.springframework.org/schema/p"

1
<bean id="book" class="pers.uang.pojo.Book" p:name="人间失格" p:author="太宰治"></bean>

注意:这个方法的底层还是使用 set 方法进行属性的注入

Xml 配置注入其他类型的属性

字面量

  1. Null 值,使用 <null /> 标签

    1
    2
    3
    4
    5
    6
    7
    8
    <bean id="book" class="pers.uang.pojo.Book">
    <constructor-arg name="name">
    <null />
    </constructor-arg>
    <constructor-arg name="author">
    <null />
    </constructor-arg>
    </bean>
  2. 属性值包含其他特殊符号

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!-- 使用转义字符 -->
    <bean id="book" class="pers.uang.pojo.Book">
    <constructor-arg name="name" value="&lt;人间失格&gt;"></constructor-arg>
    <constructor-arg name="author" value="太宰治"></constructor-arg>
    </bean>
    <!-- 使用 CDATA 方法-->
    <bean id="book" class="pers.uang.pojo.Book">
    <constructor-arg name="name">
    <value><![CDATA[<太宰治>]]></value>
    </constructor-arg>
    <constructor-arg name="author" value="太宰治"></constructor-arg>
    </bean>

注入 Bean 对象属性

  1. 外部 Bean

    1
    2
    3
    4
    5
    <!-- 向 bookService 中通过外部 Bean 方法注入属性对象-->
    <bean name="bookService" class="pers.uang.service.BookService">
    <property name="bookDAO" ref="bookDAOImpl"></property>
    </bean>
    <bean name="bookDAOImpl" class="pers.uang.dao.BookDAOImpl"></bean>
  2. 内部 Bean

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!-- 内嵌 Bean 对象,内部 Bean 方法注入属性对象 -->
    <bean id="employee" class="pers.uang.pojo.Employee">
    <property name="e_name" value="太宰治"></property>
    <property name="sex" value="男"></property>
    <property name="department">
    <bean id="department" class="pers.uang.pojo.Department">
    <property name="d_name" value="安保部"></property>
    <property name="id" value="1"></property>
    </bean>
    </property>
    </bean>
  3. 级联赋值

    方式一:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <bean id="employee" class="pers.uang.pojo.Employee">
    <property name="e_name" value="太宰治"></property>
    <property name="sex" value="男"></property>
    <property name="department" ref="dept"></property>
    </bean>
    <bean id="dept" class="pers.uang.pojo.Department">
    <property name="id" value="1"></property>
    <property name="d_name" value="技术部"></property>
    </bean>

    方式二:

    1
    2
    3
    4
    5
    6
    7
    8
    <bean id="employee" class="pers.uang.pojo.Employee">
    <property name="e_name" value="太宰治"></property>
    <property name="sex" value="男"></property>
    <property name="department" ref="dept"></property>
    <property name="department.d_name" value="安保部"></property>
    <property name="department.id" value="110"></property>
    </bean>
    <bean id="dept" class="pers.uang.pojo.Department"></bean>

注入集合类型属性

  1. 注入数组类型属性

    1
    2
    3
    4
    5
    6
    <property name="course">
    <array>
    <value>Java</value>
    <value>Python</value>
    </array>
    </property>
  2. 注入 List 集合类型属性

    1
    2
    3
    4
    5
    6
    <property name="hobbys">
    <list>
    <value>打篮球</value>
    <value>跑步</value>
    </list>
    </property>
  3. 注入 Map 集合类型属性

    1
    2
    3
    4
    5
    6
    <property name="program">
    <map>
    <entry key="JAVA" value="java"></entry>
    <entry key="PYTHON" value="python"></entry>
    </map>
    </property>
  4. 注入 Set 集合类型属性

    1
    2
    3
    4
    5
    6
    <property name="cities">
    <set>
    <value>C++</value>
    <value>JavaScript</value>
    </set>
    </property>

在集合中设置对象类型的值

方式一:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<bean id="person" class="pers.uang.pojo.Person">
<property name="goods">
<list>
<bean id="book1" class="pers.uang.pojo.Book">
<property name="name" value="人间失格"></property>
<property name="author" value="太宰治"></property>
</bean>
<bean id="boo2" class="pers.uang.pojo.Book">
<property name="name" value="骆驼祥子"></property>
<property name="author" value="鲁迅"></property>
</bean>
</list>
</property>
</bean>

方式二:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<bean id="person" class="pers.uang.pojo.Person">
<property name="goods">
<list>
<ref bean="book1"></ref>
<ref bean="book2"></ref>
</list>
</property>
</bean>
<bean id="book1" class="pers.uang.pojo.Book">
<property name="name" value="人间失格"></property>
<property name="author" value="太宰治"></property>
</bean>
<bean id="book2" class="pers.uang.pojo.Book">
<property name="name" value="骆驼祥子"></property>
<property name="author" value="鲁迅"></property>
</bean>

将集合注入部分提取成公共部分

1
2
3
4
5
6
7
8
9
<util:list id="DBList">
<value>MySQL</value>
<value>Redis</value>
<value>Oracle</value>
</util:list>

<bean id="user" class="pers.uang.pojo.User">
<property name="list" ref="DBList"></property>
</bean>

在 Spring 里可以设置 Bean 实例是单实例或者多实例,默认情况下创建的 Bean 是单实例对象。

组件扫描过滤器配置

1
2
3
4
5
6
7
8
9
<!-- 下面 xml 表示只扫描包含注解为 org.springframework.stereotype 包下的 Controller -->
<context:component-scan base-package="扫描的路径" user-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<!-- 下面 xml 表示只不扫描包含注解为 org.springframework.stereotype 包下的 Controller -->
<context:component-scan base-package="扫描的路径">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

IOC Bean 注解

Bean 标注注解

  • @Component :组件通用注解,常用于 Model 类
  • @Controller :常用于对 Controller 实现类进行标注
  • @Service:常用于对 Service 实现类进行标注
  • @Repository:常用于对 DAO 实现类进行标注

Bean 属性注入注解

  • @Value :注入普通类型属性
  • @Resource :注入对象类型
  • @Autowired :注入对象类型,默认按照类型注入。结合 @Qualifier 注解完成按名称的注入。

Bean 作用范围注解

  • @Scope :在类上添加的,控制类生成的时候采用单例还是多例
    • singleton :单例
    • prototype :多例
    • request :request域,需要在web环境
    • session :session域,需要在web环境
    • application: context域,需要在web环境
    • globalsession 集群环境的session域,需要在web环境

Bean 生命周期注解

  • @PostConstruct :相当于init-method

  • @PreDestroy :相当于destroy-method

Aop

Aop 指面向切面, 不改变源代码达到增强代码功能的技术

使用 JDK 动态代理增强方法步骤

  1. 创建接口, 定义方法
  2. 创建接口实现类, 实现接口方法
  3. 创建代理类对象, 实现 InvocationHandler 接口, 创建代理对象, 实现 invoke 增强方法

Aop 术语

连接点

​ 指的是被一个类中可以被增强的所有方法, 这些方法被称为连接点

切入点

​ 是指实际上真正被增强的那些方法称为切入点

通知(增强)

​ 实际增强的逻辑部分被称为通知 (增强)

​ 具体可分为多种类型:

​ 前置通知

​ 后置通知

​ 环绕通知

​ 异常通知

​ 最终通知

​ 当上方全部通知都存在时, 执行顺序是: 环绕前 > 前置通知 > 原方法 > 环绕后 > 最终通知 > 后置通知

切面

​ 将通知应用到切入点的过程被称为切面

Aop 操作前的准备

Spring 框架一般基于 AspectJ 实现 AOP 操作

​ AspectJ 部署 Spring 的组成部分, 是个独立的 AOP 框架, 一般将 AspectJ 和 Spring 框架一起使用, 进行 AOP 操作

基于 AspectJ 实现 Aop 操作

方法1: 基于 xml 配置文件实现

  1. 创建两个类,增强类和被增强类, 定义方法
  2. 在 spring 配置文件中创建两个类对象
  3. 在 spring 配置文件中配置切入点

方法2: 基于注解方式实现 (使用)

  1. 在 Spring 配置文件中开启注解扫描
  2. 使用注解创建 User 类 和 UserProxy 对象
  3. 在增强类上面加上注解 @Aspect
  4. 在 Spring 配置文件中开启生成代理对象
  5. 也可以通过创建配置类实现完全注解开发:
    1. @Configuration: 配置类注解, 加上此注解表示此类为配置类
    2. ComponentScan(basePackages = {“路径”}): 开启注解扫描, basePackages 设置扫描路径
    3. EnableAspectJAutoProxy(proxyTargetClass = true): 开启 Aspect 生成代理对象

Pointcut 注解可以抽取切入点, 后续的通知注解可以填写 Pointcut 注解后的方法调用起到相同的功能

Order 注解可以设置多个增强类的优先级, 值越小优先级越高

纯注解开发

  1. 通过 @Configuration 注解设置类为配置类
  2. 通过 @ComponentScan( basePackages={“路径”}) 注解 开启注解扫描
  3. 在测试调用时, 使用 AnnotationConfigApplicationContext() 来读取配置类的 Class

JdbcTemplate

JdbcTemplate 准备工作

  1. 引入 相关 jar 包

  2. 在 spring xml 配置文件中配置数据库连接池

    1
    2
    3
    4
    5
    6
    7
    <!-- 配置德鲁伊数据库连接池 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
    <property name="url" value="${prop.url}"></property>
    <property name="username" value="${prop.userName}"></property>
    <property name="password" value="${prop.password}"></property>
    <property name="driverClassName" value="${prop.driverClass}"></property>
    </bean>
  3. 配置 jdbcTemplate 对象注入 DataSource

    1
    2
    3
    4
    5
    <!-- 创建 JdbcTemplate 对象 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <!-- 注入 dataSource -->
    <property name="dataSource" ref="dataSource"></property>
    </bean>
  4. 创建 servie 、dao 类,将 jdbcTemplate 对象注入到 dao 中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // BookDaoImpl.java 源文件
    @Repository
    public class BookDaoImpl implements BookDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    }

    // BookService.java 源文件
    @Service
    public class BookService {

    @Autowired
    private BookDao bookDao;
    }
  5. 开启注解扫描

    1
    <context:component-scan base-package="pers.uang.spring5" />

Spring 中的事务管理

事务管理操作两种方式

编程式事务管理 (容易导致代码臃肿)

声明式事务管理(推荐使用)

  1. 在 Spring 中使用声明式事务管理,底层使用的是 AOP 原理

  2. 基于注解方式(推荐)

    1. 在 sprint xml 配置文件中,创建事务管理器

      1
      2
      3
      4
      <!-- 创建事务管理器 -->
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource" />
      </bean>
    2. 开启事务注解(需要引入 tx 名称空间)

      1
      2
      <!-- 开启事务注解 -->
      <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
    3. 在需要配置事务管理器的 类 或 类方法上使用 @Transactional 注解

      1. 当对类使用时,表示此类中所有方法都开启了事务管理器
      2. 当对类中方法使用时,表示此方法开启了事务管理器
    4. Transsactional 注解的参数配置,以及它的作用

      1. propagation:表示事务的传播行为

        多事务方法直接进行调用,这个过程中是如何进行管理的

      2. ioslation:事务的隔离级别

        多事务操作之间不会产生影响

      3. timeout:超时时间

        设置事务在一定时间内未进行提交操作后,就进行回滚操作,默认值为 -1 ,永不超时,单位为秒

      4. readOnly:是否只读

        设置 false,表示可以进行增、删、改、查操作,反之只能进行 查 操作,即 true 则设置为只读

      5. rollbackFor:回滚

        设置出现哪些异常进行事务的回滚

      6. noRollbackFor:不回滚

        设置出现哪些异常不进行事务的回滚

  3. 基于 xml 配置文件方式

    1. 配置事务管理器

      1
      2
      3
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource" />
      </bean>
    2. 配置通知

      1
      2
      3
      4
      5
      6
      7
      <tx:advice id="txadvice">
      <tx:attributes>
      <!-- 指定按哪种规则的方法上添加事务 -->
      <tx:method name="accountMoney"/>
      <!-- <tx:method name="account*"/> -->
      </tx:attributes>
      </tx:advice>
    3. 配置切入点、切面

      1
      2
      3
      4
      5
      <!-- 配置切入点和切面 -->
      <aop:config>
      <aop:pointcut id="pt" expression="execution(* pers.uang.spring5.service.BookService.*(..))" />
      <aop:advisor advice-ref="txadvice" pointcut-ref="pt" />
      </aop:config>
  4. 完全注解声明式事务管理
    创建配置类,使用配置类替代 xml 配置文件