Spring概述
1.概述
2.Sping5的下载
3.Spring的jar包解析
Core Container是核心部分
##4.Spring简单进行一个对象创建
public class User {
public void add(){
System.out.println("add...........");
}
}
public class Tspring1 {
@Test
public void TestAdd(){
// 加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
// 进行创建
User user = context.getBean("user", User.class);
System.out.println(user);
// Demo1.User@4466af20
user.add();
// add.............
}
}
IOC容器
底层原理:
xml解析 工厂模式 反射
1.底层原理
降低Service和Dao之间的耦合度,使用了一个工厂中间类
2.IOC的两个底层解析xml接口
FileSystem... 后面写的是绝对路径:从盘符开始写全路径
ClassPath... 后面写的是相对路径,相对于本文件
3.Bean管理操作概念
4.基于xml方式的Bean管理
1.对象的创建
2.属性的注入(DI)
####Set方式注入
Set方式注入
property
<!-- 使用set配置book-->
<bean id="book" class="Demo1.Book">
<property name="Bookname" value="new哈哈"></property>
<property name="price" value="123"></property>
</bean>
public class Book {
private Integer price;
private String bookname;
public void setBookname(String bookname) {
this.bookname = bookname;
}
public void setPrice(Integer price) {
this.price = price;
}
public Integer getPrice() {
return price;
}
public String getBookname() {
return bookname;
}
@Override
public String toString() {
return "Book{" +
"price=" + price +
", bookname='" + bookname + '\'' +
'}';
}
}
####有参构造方式注入
有参构造方式注入
constructor-arg
<!-- 使用有参构造-->
<bean id="orders" class="Demo1.Orders">
<constructor-arg name="oname" value="冬睡衣"></constructor-arg>
<constructor-arg name="price" value="1111"></constructor-arg>
</bean>
public class Orders {
private String oname;
private Integer price;
public Orders(String oname, Integer price) {
this.oname = oname;
this.price = price;
}
@Override
public String toString() {
return "Orders{" +
"oname='" + oname + '\'' +
", price=" + price +
'}';
}
}
####p名称空间注入
p名称空间注入
还可以对其简化,加入
xmlns:p="http://www.springframework.org/schema/p"
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="book1" class="Demo1.Book" p:bookname="new芜湖" p:price="12333"></bean>
其他类型属性的注入
####注入外部Bean
xml配置文件
<!-- 创建service和dao对象-->
<bean id="service" class="Demo1.service.UserService">
<!-- name: 类里面的属性名称
ref : 创建UserDao对象bean标签id值-->
<property name="userDao" ref="UserDaoImpl"></property>
</bean>
<bean id="UserDaoImpl" class="Demo1.dao.UserDaoImpl"></bean>
service程序
public class UserService {
// 创建UserDao属性,生成set方法
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("service add..........");
userDao.update();
}
}
测试类
public class Tspring {
@Test
public void TestrefBean(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
UserService service = context.getBean("service", UserService.class);
service.add();
}
}
注入内部Bean和级联赋值
内部bean
就是在创建一个对象的时候
这个对象的一个对象属性不是用value或者之前的ref
而是在<property>内部再创建一个引用的对象
相当于内部对象
<bean id="emp" class="Bean.Emp">
<property name="ename" value="huah"></property>
<property name="price" value="2312"></property>
<property name="dept">
<bean id="dept" class="Bean.Dept">
<property name="dname" value="安保部门"></property>
</bean>
</property>
</bean>
级联赋值1
<!-- 级联赋值-->
<bean id="emp1" class="Bean.Emp">
<property name="ename" value="sdas"></property>
<property name="price" value="231256"></property>
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="Bean.Dept">
<property name="dname" value="牛马部门"></property>
</bean>
级联赋值2
name="dept.dname" 需要在emp对象的类中创建getDept方法得到dept对象才能使用
<!-- 级联赋值2-->
<bean id="emp2" class="Bean.Emp">
<property name="ename" value="sdas"></property>
<property name="price" value="231256"></property>
<property name="dept" ref="dept"></property>
<property name="dept.dname" value="春牛吗部门"></property>
</bean>
注入集合属性
<bean id="stu" class="Demo2.Stu">
<property name="cs">
<array>
<value>语文</value>
<value>数学</value>
</array>
</property>
<property name="names">
<list>
<value>张三</value>
<value>李四</value>
</list>
</property>
<property name="prices">
<map>
<entry key="1" value="啊哈"></entry>
<entry key="2" value="芜湖"></entry>
</map>
</property>
</bean>
public class Stu {
private String[] cs;
private List<String> names;
private Map<Integer,String> prices;
public void setCs(String[] cs) {
this.cs = cs;
}
public void setNames(List<String> names) {
this.names = names;
}
public void setPrices(Map<Integer, String> prices) {
this.prices = prices;
}
public void pr(){
System.out.println(Arrays.toString(cs));
System.out.println(names);
System.out.println(prices);
}
}
注入对象列表的集合
使用ref来连接
把集合部分变为公共部分
名称空间 : util
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 写公共list-->
<util:list id="bookList">
<value>语文</value>
<value>英语</value>
<value>小丑</value>
</util:list>
<!-- 引入-->
<bean id="books" class="Demo2.Book">
<property name="bnames" ref="bookList"></property>
</bean>
3.工厂bean
定义类型和返回类型不一样 : 返回类型依照的是bean对象继承的接口方法中定义的
public class Bean implements FactoryBean<Course> {
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("hahahaha");//主要是这个继承的接口实现的
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
}
<bean id="bean" class="Demo2.Bean"></bean>
4.bean的作用域
@Test
public void hhh2(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");
Book books1 = context.getBean("books2", Book.class);
Book books2 = context.getBean("books2", Book.class);
Book books3 = context.getBean("books2", Book.class);
System.out.println(books1);
System.out.println(books2);
System.out.println(books3);
}
<!-- 写公共list-->
<util:list id="bookList">
<value>语文</value>
<value>英语</value>
<value>小丑</value>
</util:list>
<bean id="books2" class="Demo2.Book" scope="prototype">
<property name="bnames" ref="bookList"></property>
</bean>
5.bean的生命周期
public class Orders {
//无参数构造
public Orders() {
System.out.println("第一步 执行无参数构造创建 bean 实例");
}
private String oname;
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步 调用 set 方法设置属性值");
}
//创建执行的初始化的方法
public void initMethod() {
System.out.println("第三步 执行初始化的方法");
}
//创建执行的销毁的方法
public void destroyMethod() {
System.out.println("第五步 执行销毁的方法");
}
}
<bean id="orders" class="com.atguigu.spring5.bean.Orders" init-
method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="手机"></property>
</bean>
@Test
public void testBean3() {
//
ApplicationContext context =
//
new ClassPathXmlApplicationContext("bean4.xml");
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("bean4.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第四步 获取创建 bean 实例对象");
System.out.println(orders);
//手动让 bean 实例销毁
context.close();
}
4、bean 的后置处理器,bean 生命周期有七步
(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
(3)把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
(4)调用 bean 的初始化的方法(需要进行配置初始化的方法)
(5)把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
(6)bean 可以使用了(对象获取到了)
(7)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
5、演示添加后置处理器效果
(1)创建类,实现接口 BeanPostProcessor,创建后置处理器
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("在初始化之前执行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("在初始化之后执行的方法");
return bean;
}
}
6.自动装配
普通装配
自动装配实现
<bean id="emp" class="Bean.Emp" autowire="byName"></bean>
<bean id="dept" class="Bean.Dept">
<property name="dname" value="哈哈哈哈"></property>
</bean>
7.外部属性文件
原始直接配置
<bean id="dataSouse" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/UserDb"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
引入外部文件
创建一个外部文件jdbc.properties
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/UserDb
prop.userName=root
prop.password=123456
引入context名称空间
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:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="dataSouse" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverclass}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
##5.基于注解方式的Bean管理
###1.什么是注解
最新版的jdk版本要搭配最新版的spring,,否则就报错
<!-- 开启组件扫描-->
<context:component-scan base-package="Demo3.service"></context:component-scan>
//注解属性值可以不写,默认是类名称的小写
@Component(value = "userService") //<bean id="userService" class=".."/>
public class UserService {
public void add() {
System.out.println("service add.......");
}
}
@Test
public void testService(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
2.组件扫描配置
3.属性的注入
@Autowired
@Repository
public class UserDaoImpl implements UserDao{
@Override
public void add() {
System.out.println("Dao.......... add........");
}
}
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void add() {
System.out.println("service add.......");
userDao.add();
}
}
@Qualifier根据名称注入,要在需要注入的对象类用该注解加上名称
并且在注入的目的类里搭配@Autowired一起使用
4.完全注解开发
创建配置类,替代xml文件
@Configuration
@ComponentScan(basePackages = {"Demo3"})
public class ConfigSpring {
}
使用 : AnnotationConfigApplicationContext和反射来获取context
@Test
public void testService2(){
ApplicationContext context = new AnnotationConfigApplicationContext(ConfigSpring.class);
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
AOP容器
1.概念
2.底层原理
3.动态代理(JDK)的底层代码
实现对子类对象方法的增强而不改变其源代码
先创建一个接口数组,对象是UserDao
再把要增强的UserDaoImpl对象创建并传到Proxy.newProxyInstance中去
new UserDaoProxy(userDao) :
实现InvocationHandler接口
在UserDaoProxy中:
创建的是谁的代理对象
有参构造传递
这时获取到了要创建的代理对象UserDaoImpl
重写invoke方法:
(该方法的功能是在每次调用代理对象的方法时,都会运行)
method会得到当前的方法
obj是代理对象
args是参数
执行当前增强的方法
Object res = method.invoke(obj,args);
public class JDKproxy {
public static void main(String[] args) {
// 创建接口实现类代理对象
Class[] interfaces = {UserDao.class};
UserDaoImpl userDao = new UserDaoImpl();
UserDao dao = (UserDao) Proxy.newProxyInstance(JDKproxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
dao.add(1,2);
}
}
class UserDaoProxy implements InvocationHandler{
// 创建的是谁的代理对象
// 有参构造传递
private Object obj;
public UserDaoProxy(Object obj){
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 方法之前执行
System.out.println("方法之前执行....."+method.getName()+": 传递的参数"+ Arrays.toString(args));
// 执行当前增强的方法
Object res = method.invoke(obj,args);
// 方法之后
System.out.println("方法之后"+obj);
return res;
}
}
4.AOP操作术语
5.AOP使用的准备
6. 基于AspectJ的注解
Test
@Test
public void testAOP(){
//来自内容根的路径
ApplicationContext context = new FileSystemXmlApplicationContext("src/AOPDemo/b1.xml");
User user = context.getBean("user", User.class);
user.add();
}
要增强的方法的对象
@Component
public class User {
public void add(){
System.out.println("原始的add方法。。。。。。。");
}
}
增强的逻辑实现
@Component
@Aspect //生成注解代理对象
public class UserProxy {
// 前置通知
@Before(value = "execution(* AOPDemo.User.add(..))")
public void before(){
System.out.println("前置增强。。。。。。。。");
}
}
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:aop="http://www.springframework.org/schema/aop"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解扫描-->
<context:component-scan base-package="AOPDemo"></context:component-scan>
<!-- 开启生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
加入其它类型的通知之后
@Component
@Aspect //生成注解代理对象
public class UserProxy {
// 前置通知
@Before(value = "execution(* AOPDemo.User.add(..))")
public void before(){
System.out.println("前置增强。。。。。。。。");
}
// 后置通知
@After(value = "execution(* AOPDemo.User.add(..))")
public void after(){
System.out.println("后置增强.........");
}
// 环绕通知
@Around(value = "execution(* AOPDemo.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕通知之前。。。。。");
proceedingJoinPoint.proceed();
System.out.println("环绕通知之后。。。。。");
}
}
抽取相同切入点
设置优先级
JdbcTemplate操作数据库
1.概念和准备工作
导入依赖
创建数据库连接池
配置jdbcTemplete对象
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="jdbc:mysql:///book" />
<property name="username" value="root" />
<property name="password" value="123456" />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
2.数据库的添加功能
BookDaoImpl
@Override
public void add(Book book) {
String sql="insert into books values(?,?,?)";
int update = jdbcTemplate.update(sql,book.getBookId(), book.getName(), book.getUstatus());
}
Test
@Test
public void add(){
ApplicationContext context = new FileSystemXmlApplicationContext("src/TempleteDemo/b2.xml");
BookService bookService = context.getBean("bookService", BookService.class);
bookService.addBook(new Book("你好世界2","哈哈哈哈2"));
}
##3.修改和删除功能
@Override
public void up(Integer id, Book book) {
String sql="update books set name = ? , ustatus = ? where bookId=?";
jdbcTemplate.update(sql,book.getName(),book.getUstatus(),id);
}
@Override
public void delete(Integer id) {
String sql="delete from books where bookId = ?";
jdbcTemplate.update(sql,id);
}
@Test
public void up(){
ApplicationContext context = new FileSystemXmlApplicationContext("src/TempleteDemo/b2.xml");
BookService bookService = context.getBean("bookService", BookService.class);
bookService.up(3,new Book("我不好","所以呢"));
}
@Test
public void delete(){
ApplicationContext context = new FileSystemXmlApplicationContext("src/TempleteDemo/b2.xml");
BookService bookService = context.getBean("bookService", BookService.class);
bookService.delete(4);
}
4.查找功能
单个查找
@Override
public Book look(String name) {
String sql = "select * from books where name = ?";
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Book.class), name);
return book;
}
多个查找
@Override
public List<Book> looks(String us) {
String sql = "select * from books where ustatus = ?";
List<Book> books = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Book.class), us);
return books;
}
5.批量功能
添加
@Override
public void adds(List<Object[]> books) {
String sql="insert into books(name,ustatus) values(?,?)";
jdbcTemplate.batchUpdate(sql,books);
}
@Test
public void adds(){
ApplicationContext context = new FileSystemXmlApplicationContext("src/TempleteDemo/b2.xml");
BookService bookService = context.getBean("bookService", BookService.class);
List<Object[]> objects = new ArrayList<>();
Object[] o1 = {"sda ","3"};
Object[] o2 = {"sfsdfa ","3"};
Object[] o3 = {"ddddd ","3"};
objects.add(o1);
objects.add(o2);
objects.add(o3);
bookService.adds(objects);
}
修改
@Override
public void ups(List<Object[]> books) {
String sql="update books set bookname = ? , ustatus = ? where bookId = ?";
int[] ints = jdbcTemplate.batchUpdate(sql, books);
System.out.println(ints);
}
@Test
public void ups(){
ApplicationContext context = new FileSystemXmlApplicationContext("src/TempleteDemo/b2.xml");
BookService bookService = context.getBean("bookService", BookService.class);
List<Object[]> objects = new ArrayList<>();
Object[] o1 = {"ds ","5",8};
Object[] o2 = {"sf ","4",9};
objects.add(o1);
objects.add(o2);
bookService.ups(objects);
}
事务操作
1.概念
2.环境搭建
3.事务操作
4.注解方式操作
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">
<!-- 事务管理-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启事务注解-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"></tx:annotation-driven>
dao
@Repository
public class UserDaoImpl implements UserDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void add(int money,String name) {
String sql = "update bank set money = money+? where username = ?";
jdbcTemplate.update(sql,money,name);
}
@Override
public void delete(int money,String name) {
String sql = "update bank set money = money-? where username = ?";
jdbcTemplate.update(sql,money,name);
}
}
service
@Service
@Transactional //事务开启注解
public class UserService {
@Autowired
private UserDao userDao;
public void action(){
// int money;
// Scanner scanner = new Scanner(System.in);
// money = scanner.nextInt();
userDao.add(100,"xiao");
int c = 1/0;
userDao.delete(100,"zhang");
}
}
test
public class Test {
@org.junit.Test
public void test(){
ApplicationContext context = new FileSystemXmlApplicationContext("src/SpringTransaction/b3.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.action();
}
}
成功
有异常
5.事务操作中的属性
###传播行为
传播行为
###隔离级别
隔离级别
当那个事务回滚以后,将导致另一个对其进行读取的事务的值无法跟着修改,因为第一个事务还未提交,所以它可以无限的修改数值,但是另一个只能读取一次
一个未提交的事务读取到另一个已经提交的事务的数据,但是1的数据是2的提交之前的,所以说会导致1的值与事实不符
解决
###其他参数
其他参数
6.完全注解方法
Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。Spring只会调用一次,将这个Bean对象放在自己的IOC容器中。
通俗的将就是在服务启动时,实例化一个对象放到ioc容器中,在需要初始化的实例,方法,内容时使用。
未指定bean 的名称,默认采用的是 "方法名" + "首字母小写"的配置方式
@Configuration
@ComponentScan(basePackages = "SpringTransaction")//组件扫描
@EnableTransactionManagement//开启事务
public class TxConfig {
// 创建数据库连接池对象
@Bean
public DruidDataSource getDruidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUrl("jdbc:mysql:///book");
druidDataSource.setUsername("root");
druidDataSource.setPassword("123456");
return druidDataSource;
}
// 创建JdbcTemplate对象
@Bean
public JdbcTemplate getJdbcTemplate(DruidDataSource druidDataSource){
JdbcTemplate jdbcTemplate = new JdbcTemplate();
// 到ioc容器中找到druidDataSource
jdbcTemplate.setDataSource(druidDataSource);
return jdbcTemplate;
}
// 创建事务管理对象
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DruidDataSource druidDataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
// 到ioc容器中找到druidDataSource
transactionManager.setDataSource(druidDataSource);
return transactionManager;
}
}
Test
public void test(){
ApplicationContext context = new AnnotationConfigApplicationContext(TxConfig.class);
UserService userService = context.getBean("userService", UserService.class);
userService.action();
}
7.AOP在事务中的应用
创建一个切面类
package com.zxy.aspect;
import com.zxy.tx.MyTransactionManager;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author ZXY
* @version 1.0
* @date 2020/12/19 17:32
* 日志切面类
*/
@Component
@Aspect
public class TransactionAspect {
@Autowired
private MyTransactionManager transactionManager;// 引入自定义事务类
// 配置切入点
@Pointcut("execution(* com.zxy.service.impl.*.*(..))")
private void pointcut(){}
@Before("pointcut()")
public void beforeAdvice(){
System.out.println("**************** 开启事务!***************");
transactionManager.begin();
}
@AfterReturning("pointcut()")
public void afterReturning(){
System.out.println("**************** 提交事务***************");
transactionManager.commit();
}
@AfterThrowing("pointcut()")
public void afterThrowing(){
System.out.println("**************** 回滚事务***************");
transactionManager.rollback();
}
@After("pointcut()")
public void afterAdvice(){
System.out.println("**************** 释放资源!***************");
transactionManager.close();
}
}
为启动类添加注解@EnableAspectJAutoProxy开启Spring对AOP的支持:
@EnableAspectJAutoProxy
@Configuration
@ComponentScan({"com.zxy"})
@Import({MybatisConfig.class,DataSourceConfig.class})
public class SpringConfig {}
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration( classes = {SpringConfig.class})
public class Test1 {
@Autowired
@Qualifier("accountServiceImpl")
private IAccountService accountService;
@Test
public void test1(){
// 张三转账给李四1000元
accountService.transfer("zhangsan","lisi",1000.0);
}
}
正常情况:
发生异常,事务回滚:
#Spring5新功能:
##整合日志框架
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,可以看到log4j2内部各种详细输出-->
<configuration status="INFO">
<!--先定义所有的appender-->
<appenders>
<!--输出日志信息到控制台-->
<console name="Console" target="SYSTEM_OUT">
<!--控制日志输出的格式-->
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</console>
</appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<!--root:用于指定项目的根日志,如果没有单独指定Logger,则会使用root作为默认的日志输出-->
<loggers>
<root level="info">
<appender-ref ref="Console"/>
</root>
</loggers>
</configuration>
@Nullable和函数式编程对象
整合Junit5单元测试框架
Junit4
Junit5
复合注解替代上面两个注解
SpringWebFlux
基本概念
对乘客:
我在等公交车时可以打游戏,而不是干等着-----异步
对公交车:
收到乘客的上车请求,我立刻发一个通知给乘客说还有几分钟到站---------非阻塞
与SpringMVC的区别与联系
使用场景:
在有限的容量下处理更多的操作和请求
###响应式编程
a+b=c : 之后改变a的值会直接改变c的值
模拟响应式编程的执行:
当对象改变时,观察者观察到了改变然后做出相应的操作
用Reactor的部分API实现响应式编程
发布
订阅
操作
map :元素映射成新的元素
flatmap :元素映射成流
WebFlux执行流程与核心API
BIO:阻塞方式
NIO:非阻塞
执行过程
handle的底层源代码
需要的API
基于注解的编程模型
用户接口
接口实现
package New;
public class UserServiceImpl implements UserService {
//创建 map 集合存储数据
private final Map<Integer,User> users = new HashMap<>();
public UserServiceImpl() {
this.users.put(1,new User("lucy","nan",20));
this.users.put(2,new User("mary","nv",30));
this.users.put(3,new User("jack","nv",50));
}
//根据 id 查询
@Override
public Mono<User> getUserById(int id) {
return Mono.justOrEmpty(this.users.get(id));
}
//查询多个用户
@Override
public Flux<User> getAllUser() {
return Flux.fromIterable(this.users.values());
}
//添加用户
@Override
public Mono<Void> saveUserInfo(Mono<User> userMono) {
return userMono.doOnNext(person -> {
//向 map 集合里面放值
int id = users.size()+1;
users.put(id,person);
}).thenEmpty(Mono.empty());
}
}
Controller控制层
@RestController
public class UserController {
//注入 service
@Autowired
private UserService userService;
//id 查询
@GetMapping("/user/{id}")
public Mono<User> geetUserId(@PathVariable int id) {
return userService.getUserById(id);
}
//查询所有
@GetMapping("/user")
public Flux<User> getUsers() {
return userService.getAllUser();
}
//添加
@PostMapping("/saveuser")
public Mono<Void> saveUser(@RequestBody User user) {
Mono<User> userMono = Mono.just(user);
return userService.saveUserInfo(userMono);
}
}