IOC
Sprint 配置的两种基本注入属性方法
依赖 bean 对象中的 set 方法进行属性的注入:
<bean id="book" class="pers.uang.pojo.Book">
<property name="name" value="人间失格"></property>
<property name="author" value="太宰治"></property>
</bean>依赖 bean 对象的有参构造器进行属性的注入:
<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 属性,可用通过索引来对构造器中对应位置上的参数进行属性注入:
<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" :
<bean id="book" class="pers.uang.pojo.Book" p:name="人间失格" p:author="太宰治"></bean>**注意:**这个方法的底层还是使用 set 方法进行属性的注入
Xml 配置注入其他类型的属性
字面量
Null 值,使用
<null />标签<bean id="book" class="pers.uang.pojo.Book"> <constructor-arg name="name"> <null /> </constructor-arg> <constructor-arg name="author"> <null /> </constructor-arg> </bean>属性值包含其他特殊符号
<!-- 使用转义字符 --> <bean id="book" class="pers.uang.pojo.Book"> <constructor-arg name="name" value="<人间失格>"></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 对象属性
外部 Bean
<!-- 向 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>内部 Bean
<!-- 内嵌 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>级联赋值
方式一:
<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>方式二:
<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>
注入集合类型属性
注入数组类型属性
<property name="course"> <array> <value>Java</value> <value>Python</value> </array> </property>注入 List 集合类型属性
<property name="hobbys"> <list> <value>打篮球</value> <value>跑步</value> </list> </property>注入 Map 集合类型属性
<property name="program"> <map> <entry key="JAVA" value="java"></entry> <entry key="PYTHON" value="python"></entry> </map> </property>注入 Set 集合类型属性
<property name="cities"> <set> <value>C++</value> <value>JavaScript</value> </set> </property>
在集合中设置对象类型的值
方式一:
<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>方式二:
<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>将集合注入部分提取成公共部分
<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 是单实例对象。
组件扫描过滤器配置
<!-- 下面 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 动态代理增强方法步骤
- 创建接口, 定义方法
- 创建接口实现类, 实现接口方法
- 创建代理类对象, 实现 InvocationHandler 接口, 创建代理对象, 实现 invoke 增强方法
Aop 术语
连接点
指的是被一个类中可以被增强的所有方法, 这些方法被称为连接点
切入点
是指实际上真正被增强的那些方法称为切入点
通知(增强)
实际增强的逻辑部分被称为通知 (增强)
具体可分为多种类型:
前置通知
后置通知
环绕通知
异常通知
最终通知
当上方全部通知都存在时, 执行顺序是: 环绕前 > 前置通知 > 原方法 > 环绕后 > 最终通知 > 后置通知
切面
将通知应用到切入点的过程被称为切面
Aop 操作前的准备
Spring 框架一般基于 AspectJ 实现 AOP 操作
AspectJ 部署 Spring 的组成部分, 是个独立的 AOP 框架, 一般将 AspectJ 和 Spring 框架一起使用, 进行 AOP 操作
基于 AspectJ 实现 Aop 操作
方法1: 基于 xml 配置文件实现
- 创建两个类,增强类和被增强类, 定义方法
- 在 spring 配置文件中创建两个类对象
- 在 spring 配置文件中配置切入点
方法2: 基于注解方式实现 (使用)
- 在 Spring 配置文件中开启注解扫描
- 使用注解创建 User 类 和 UserProxy 对象
- 在增强类上面加上注解 @Aspect
- 在 Spring 配置文件中开启生成代理对象
- 也可以通过创建配置类实现完全注解开发:
- @Configuration: 配置类注解, 加上此注解表示此类为配置类
- ComponentScan(basePackages = {"路径"}): 开启注解扫描, basePackages 设置扫描路径
- EnableAspectJAutoProxy(proxyTargetClass = true): 开启 Aspect 生成代理对象
Pointcut 注解可以抽取切入点, 后续的通知注解可以填写 Pointcut 注解后的方法调用起到相同的功能
Order 注解可以设置多个增强类的优先级, 值越小优先级越高
纯注解开发
- 通过 @Configuration 注解设置类为配置类
- 通过 @ComponentScan( basePackages={"路径"}) 注解 开启注解扫描
- 在测试调用时, 使用 AnnotationConfigApplicationContext() 来读取配置类的 Class
JdbcTemplate
JdbcTemplate 准备工作
引入 相关 jar 包
在 spring xml 配置文件中配置数据库连接池
<!-- 配置德鲁伊数据库连接池 --> <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>配置 jdbcTemplate 对象注入 DataSource
<!-- 创建 JdbcTemplate 对象 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <!-- 注入 dataSource --> <property name="dataSource" ref="dataSource"></property> </bean>创建 servie 、dao 类,将 jdbcTemplate 对象注入到 dao 中
// BookDaoImpl.java 源文件 @Repository public class BookDaoImpl implements BookDao { @Autowired private JdbcTemplate jdbcTemplate; } // BookService.java 源文件 @Service public class BookService { @Autowired private BookDao bookDao; }开启注解扫描
<context:component-scan base-package="pers.uang.spring5" />
Spring 中的事务管理
事务管理操作两种方式
编程式事务管理 (容易导致代码臃肿)
声明式事务管理(推荐使用)
在 Spring 中使用声明式事务管理,底层使用的是 AOP 原理
基于注解方式(推荐)
在 sprint xml 配置文件中,创建事务管理器
<!-- 创建事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>开启事务注解(需要引入 tx 名称空间)
<!-- 开启事务注解 --> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>在需要配置事务管理器的 类 或 类方法上使用 @Transactional 注解
- 当对类使用时,表示此类中所有方法都开启了事务管理器
- 当对类中方法使用时,表示此方法开启了事务管理器
Transsactional 注解的参数配置,以及它的作用
propagation:表示事务的传播行为
多事务方法直接进行调用,这个过程中是如何进行管理的
ioslation:事务的隔离级别
多事务操作之间不会产生影响
timeout:超时时间
设置事务在一定时间内未进行提交操作后,就进行回滚操作,默认值为 -1 ,永不超时,单位为秒
readOnly:是否只读
设置 false,表示可以进行增、删、改、查操作,反之只能进行 查 操作,即 true 则设置为只读
rollbackFor:回滚
设置出现哪些异常进行事务的回滚
noRollbackFor:不回滚
设置出现哪些异常不进行事务的回滚
基于 xml 配置文件方式
配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>配置通知
<tx:advice id="txadvice"> <tx:attributes> <!-- 指定按哪种规则的方法上添加事务 --> <tx:method name="accountMoney"/> <!-- <tx:method name="account*"/> --> </tx:attributes> </tx:advice>配置切入点、切面
<!-- 配置切入点和切面 --> <aop:config> <aop:pointcut id="pt" expression="execution(* pers.uang.spring5.service.BookService.*(..))" /> <aop:advisor advice-ref="txadvice" pointcut-ref="pt" /> </aop:config>
完全注解声明式事务管理 创建配置类,使用配置类替代 xml 配置文件