Spring 笔记
IOC
set 注入属性
bean
public class Book {
//创建属性
private String bname;
private String bauthor;
//创建属性对应的 set 方法
public void setBname(String bname) {
this.bname = bname;
}
public void setBauthor(String bauthor) {
this.bauthor = bauthor;
}
}
Spring xml配置文件
<bean id="book" class="com.atguigu.spring5.Book">
<property name="bname" value="易筋经"></property>
<property name="bauthor" value="达摩老祖"></property>
</bean>
有参构造注入
bean
public class Orders {
//属性
private String oname;
private String address;
//有参数构造
public Orders(String oname,String address) {
this.oname = oname;
this.address = address;
}
}
Spring XML 配置文件
constructor-arg
也可以使用 index
(从0开始
<bean id="orders" class="com.atguigu.spring5.Orders">
<constructor-arg name="oname" value="电脑"></constructor-arg>
<constructor-arg name="address" value="China"></constructor-arg>
</bean>
p 名称空间注入
<bean id="book" class="com.atguigu.spring5.Book" p:bname="九阳神功" p:bauthor="无名氏"></bean>
XML 注入 null 或 特殊字符
null值
<property name="address">
<null/>
</property>
特殊字符
<!--属性值包含特殊符号
1 把<>进行转义 < >
2 把带特殊符号内容写到 CDATA
-->
<property name="address">
<value><![CDATA[<<南京>>]]></value>
</property>
注入属性-bean
外部 bean
<bean id="userService" class="com.atguigu.spring5.service.UserService">
<property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"></bean>
内部 bean
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
<property name="dept">
<bean id="dept" class="com.atguigu.spring5.bean.Dept">
<property name="dname" value="安保部"></property>
</bean>
</property>
</bean>
注入属性-集合
<bean id="stu" class="com.atguigu.spring5.collectiontype.Stu">
<!--数组类型属性注入-->
<property name="courses">
<array>
<value>java</value>
<value>数据库 de</value>
</array>
</property>
<!--list 类型属性注入-->
<property name="list">
<list>
<value>张三</value>
<value>小三</value>
</list>
</property>
<!--map 类型属性注入-->
<property name="maps">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
<!--set 类型属性注入-->
<property name="sets">
<set>
<value>MySQL</value>
<value>Redis</value>
</set>
</property>
</bean>
给集合注入值
<bean id="course1" class="com.atguigu.spring5.collectiontype.Course">
<property name="cname" value="Spring5 框架"></property>
</bean>
<bean id="course2" class="com.atguigu.spring5.collectiontype.Course">
<property name="cname" value="MyBatis 框架"></property>
</bean>
<!--注入 list 集合类型,值是对象-->
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
集合的提取和注入
<util:list id="bookList">
<value>易筋经</value>
<value>九阴真经</value>
<value>九阳神功</value>
</util:list>
<!--2 提取 list 集合类型属性注入使用-->
<bean id="book" class="com.atguigu.spring5.collectiontype.Book">
<property name="list" ref="bookList"></property>
</bean>
工厂bean
实现 FactoryBean<T>
接口
设置bean 为多实例
默认是单实例,设置多实例方法为:
更改 scope
参数
<bean id="user" class="cc.acdongla.UserImpl" scope="prototype"></bean>
单实例和多实例区别
1. singleton 单实例,prototype 多实例
2. 单实例在加载配置文件时创建对象,多实例在调用 getbean() 方法时创建对象
自动装配
bean 标签属性 autowire,配置自动装配
autowire 属性常用两个值:
byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样
byType 根据属性类型注入
引入properties文件配置数据库连接池
${属性名} (等号左边)
<!--引入外部属性文件-->
<context:property-placeholder location="classpath:jdbc.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.userName}"></property>
<property name="password" value="${prop.password}"></property>
</bean>
基于注解方式实现属性注入
@Autowired:根据属性类型进行自动装配
@Qualifier:根据名称进行注入, 和上面@Autowired 一起使用
@Resource:可以根据类型注入,可以根据名称注入。默认根据类型注入
@Value:注入普通类型属性
示例:
@Repository(value = "user1")
public class UserDapImpl implements UserDao {
@Resource(name = "user1")
private UserDao userDao;
完全注解开发
@Configuration // 作为配置类,替代XML文件
@ComponentScan(basePackages = "cc.acdongla.demo01") // 加载配置类是自动装载该路径下的类
public class SpringConfig {}
AOP操作
切入点表达式
作用: 知道对那个类里的方法进行增强
语法结构
execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))
举例
对cc.acdongla.dao.UserDao里面的add进行增强
execution(* cc.acdongla.dao.UserDao.add(..))
对cc.acdongla.dao.UserDao里面的所有方法增强
execution(* cc.acdongla.dao.UserDao.*(..))
对cc.acdongla.dao包里的所有类所有方法进行增强
execution(* cc.acdongla.dao.*.*(..))
Aspect 注解
Spring 配置文件设置:
被增强类
![](https://img2020.cnblogs.com/blog/2439937/202109/2439937-20210928181850356-1181512638.png)
增强类
@Aspect
:生成代理对象
@Before
:前置通知
![](https://img2020.cnblogs.com/blog/2439937/202109/2439937-20210928181850757-2053931932.png)
测试运行
运行结果
![](https://img2020.cnblogs.com/blog/2439937/202109/2439937-20210928181851100-1821330311.png)
不同类型的通知
@Before 前置通知
@AfterReturning 后置通知(返回通知),若出现异常不通知
@After 最终通知,出现异常也会通知
@AfterThrowing 异常通知,只有出现异常才通知
@Around 环绕通知
@Around
环绕通知使用示例
@Around(value = "execution(* cc.acdongla.aopanno.Person.run(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前");
proceedingJoinPoint.proceed(); // 被增强的方法执行
System.out.println("环绕之后");
}
多个切入点抽取
使用注解 @Pointcut
![](https://img2020.cnblogs.com/blog/2439937/202109/2439937-20210928181851774-729954434.png)
多个增强类设置优先级
增强类添加 @Order 注解,传递一个数字值,值越小优先级越高,从0开始
![](https://img2020.cnblogs.com/blog/2439937/202109/2439937-20210928181852259-1268749176.png)
JdbcTemplate
准备工作
- 需要的jar包
- Spring 配置--开启组件扫描
<context:component-scan base-package="cc.acdongla"></context:component-scan>
- Spring 配置--数据库连接池
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="jdbc:mysql:///test" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
-
Spring 配置--创建JdbcTemplate实现
JdbcTemplate中需要数据库连接池对象
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
-
在Dao类中自动装载JdbcTemplate对象
@Repository public class BookDaoImpl implements BookDao{ @Autowired private JdbcTemplate jdbcTemplate; }
-
在Service类中自动装载Dao对象
@Service public class BookService { @Autowired private BookDao bookDao; }
完整配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="cc.acdongla"></context:component-scan>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="jdbc:mysql:///test" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
增删改示例
new JdbcTemplate().update 负责增删改操作
要添加一部书到数据库
Book: 该类为数据库t_book表的实体类
BookDaoImpl
@Repository
public class BookDaoImpl implements BookDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public int add(Book book) {
String sql = "insert into t_book values(?,?,?)";
return jdbcTemplate.update(sql, book.getBname(), book.getAuthor(), book.getPrice());
}
}
BookService
@Service
public class BookService {
@Autowired
private BookDao bookDao;
public void addBook() {
int count = bookDao.add(new Book("Java编程思想", "王一赫", 9999.999));
System.out.println(count);
}
}
测试方法
@Test
public void test1() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
BookService bookService = (BookService) context.getBean("bookService");
bookService.addBook();
}
查询-返回单个值
示例:查询表的数据条数
public int queryCount() {
String sql = "select count(*) from t_book";
return jdbcTemplate.queryForObject(sql, Integer.class);
}
查询-返回对象
自动封装Bean
new BeanPropertyRowMapper<>(Book.class)
: 参数传递 Bean.class
示例:一个书籍所有信息
public Book queryBook(double price) {
String sql = "select * from t_book where price=?";
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Book.class), price);
return book;
}
查询-返回集合
直接使用query()函数,参数使用和上面的一样
示例:查找所有书籍的信息
public List<Book> queryAllBook() {
String sql = "select * from t_book";
List<Book> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Book.class));
return query;
}
批量-增删改
传入List<Object[]>
,函数会遍历 list ,把Object里的内容提取出来,以此实现批量更新的操作。返回每次操作的影响行数
示例:批量插入
@Override
public int[] batchAddBooks(List<Object[]> list) {
String sql = "insert into t_book values(?,?,?)";
int[] ints = jdbcTemplate.batchUpdate(sql, list);
return ints;
}
声明式事务管理
开启事务
配置文件中加入事务管理bean
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
开启事务注解
开启id为transactionManager
的事务管理类的注解
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
使用事务注解
@Transactional
加在类上面,该类的所有方法都会被添加上事务
加在方法上面,只有该方法会添加上事务
示例:
@Service
@Transactional
public class UserService {
@Autowired
private UserDao userDao;
public void addAndReduce() {
userDao.addMoney();
// int a = 10/0;
userDao.reduceMoney();
}
}
完整XML配置参考:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
">
<context:component-scan base-package="cc.acdongla"></context:component-scan>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="jdbc:mysql:///test" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 事务管理类-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>
jar包参考:
![](https://img2020.cnblogs.com/blog/2439937/202109/2439937-20210928181854143-36530370.png)
propagation-事务传播行为
默认为REQUIRED
使用示例
@Transactional(propagation = Propagation.REQUIRED)
常用的是前两个
isolation-事务隔离级别
示例:
@Transactional(isolation = Isolation.READ_COMMITTED)
默认:REPEATABLE_READ
可重复读
脏读: 一个未提交事务读取到另一个未提交事务中已改变的数据,之后该事务又回滚
不可重复读: 一个未提交事务读取到一个已提交事务修改的数据
幻读: 一个未提交事务读取到一个已提交事务添加的数据
timeout-超时时间
- 事务需要在指定实现内提交,否则回滚
- 默认值为-1,设置的单位是秒
示例:
@Transactional(timeout = 10)
readOnly-是否只读
-
只读:只支持数据的查询操作,不支持增删改
-
默认为false,支持增删改查
示例:
@Transactional(readOnly = true)
异常回滚
rollbackFor: 出现那些异常进行回滚
noRollbackFor: 出现那些异常不进行回滚
示例:
@Transactional(noRollbackFor = NullPointerException.class)
完全注解配置方式
TxConfig.java
package cc.acdongla.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration // 配置类
@ComponentScan(basePackages = "cc.acdongla") // 组件扫描
@EnableTransactionManagement // 开启事务管理
public class TxConfig {
// 创建数据库连接池
@Bean
public DruidDataSource getDruidDataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUrl("jdbc:mysql:///test");
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUsername("root");
druidDataSource.setPassword("root");
return druidDataSource;
}
// 创建jdbcTemplate类
@Bean
public JdbcTemplate getJdbcTemplate(DruidDataSource druidDataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(druidDataSource);
return jdbcTemplate;
}
// 事务管理类
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DruidDataSource druidDataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new
DataSourceTransactionManager(druidDataSource);
return dataSourceTransactionManager;
}
}