Spring5学习笔记

100 阅读11分钟

Spring概述

1.概述

image-20211122154346137

2.Sping5的下载

image-20211122160000641

image-20211122160036544

image-20211122160054894

3.Spring的jar包解析

image-20211122160430387

Core Container是核心部分

image-20211122161019085

##4.Spring简单进行一个对象创建

image-20211122161429221

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容器

image-20211122162641403

image-20211122162911859

底层原理:
xml解析   工厂模式   反射

1.底层原理

image-20211122163330783

降低Service和Dao之间的耦合度,使用了一个工厂中间类

image-20211122163654496

image-20211122164512062

2.IOC的两个底层解析xml接口

image-20211122165559341

image-20211122165647531

FileSystem...    后面写的是绝对路径:从盘符开始写全路径
ClassPath...     后面写的是相对路径,相对于本文件

3.Bean管理操作概念

image-20211123202724834

image-20211123202848454

4.基于xml方式的Bean管理

1.对象的创建

image-20211123205017863

2.属性的注入(DI)

image-20211123211250509

####Set方式注入

Set方式注入
property
<!--    使用set配置book-->
    <bean id="book" class="Demo1.Book">
        <property name="Bookname" value="new哈哈"></property>
        <property name="price" value="123"></property>
    </bean>

image-20211123210743856

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>

image-20211123212033841

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>

其他类型属性的注入

image-20211123214829465

image-20211123215242299

####注入外部Bean

image-20211123220242481

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();

    }
}

image-20211123222002031

注入内部Bean和级联赋值

内部bean
就是在创建一个对象的时候
这个对象的一个对象属性不是用value或者之前的ref
而是在<property>内部再创建一个引用的对象
相当于内部对象

image-20211124214034605

<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>

image-20211124221159597

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来连接

image-20211124221901487

image-20211124221921097

把集合部分变为公共部分

名称空间   :   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">

image-20211124222741871

<!--    写公共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对象继承的接口方法中定义的

image-20211125192140978

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>

image-20211125192941857

4.bean的作用域

image-20211125194117668

image-20211125194529909

@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的生命周期

image-20211125200340573

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;
      }
}

image-20211125202711084

6.自动装配

image-20211125205428653

普通装配

image-20211125204409480

自动装配实现

image-20211125205351155

<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,,否则就报错

image-20211126084538495

image-20211126085557876

<!--    开启组件扫描-->
    <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.组件扫描配置

image-20211126092621916

3.属性的注入

image-20211126212345375

@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();
    }
}

image-20211126213218875

@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.概念

image-20211127163216920

image-20211127163247951

2.底层原理

image-20211127164029160

image-20211127164254488

3.动态代理(JDK)的底层代码

实现对子类对象方法的增强而不改变其源代码

image-20211127164946936

image-20211127171208574

先创建一个接口数组,对象是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操作术语

image-20211130161108037

5.AOP使用的准备

image-20211130161430988

image-20211130161722050

image-20211130162354457

6. 基于AspectJ的注解

image-20211130165842216

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>
加入其它类型的通知之后

image-20211130170641146

@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("环绕通知之后。。。。。");
    }
}
抽取相同切入点

image-20211130184937453

设置优先级

image-20211130185408069

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>

image-20211201103558016

2.数据库的添加功能

image-20211201103738909

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;
}

image-20211202104303885

多个查找
@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;
}

image-20211202105210104

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.概念

image-20211202150505867

2.环境搭建

image-20211202153338419

3.事务操作

image-20211202155839420

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();
    }
}
成功

image-20211202162018248

有异常

image-20211202161955691

5.事务操作中的属性

image-20211202211825337

###传播行为

传播行为

image-20211202211010285

###隔离级别

隔离级别

image-20211202213542696

当那个事务回滚以后,将导致另一个对其进行读取的事务的值无法跟着修改,因为第一个事务还未提交,所以它可以无限的修改数值,但是另一个只能读取一次

image-20211202214228924

一个未提交的事务读取到另一个已经提交的事务的数据,但是1的数据是2的提交之前的,所以说会导致1的值与事实不符

image-20211202214520890

解决

image-20211202214724788

###其他参数

其他参数

image-20211202215306149

image-20211202215427619

image-20211202215449267

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新功能:

##整合日志框架

image-20211203154827121

<?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>

image-20211203162016080

@Nullable和函数式编程对象

image-20211203162831015

image-20211203164119332

整合Junit5单元测试框架

image-20211203164511215

Junit4

image-20211203164428202

Junit5

image-20211203165130024

复合注解替代上面两个注解

image-20211203165451299

SpringWebFlux

基本概念

image-20211203171124807

image-20211203180643179

对乘客:
我在等公交车时可以打游戏,而不是干等着-----异步
对公交车:
收到乘客的上车请求,我立刻发一个通知给乘客说还有几分钟到站---------非阻塞
与SpringMVC的区别与联系

image-20211203181509814

使用场景:

在有限的容量下处理更多的操作和请求

image-20211203181800225

###响应式编程

image-20211203182434072

a+b=c  :  之后改变a的值会直接改变c的值

image-20211203182416495

模拟响应式编程的执行:
当对象改变时,观察者观察到了改变然后做出相应的操作

image-20211203183524600

用Reactor的部分API实现响应式编程

image-20211203185704189

image-20211203185739076

发布

image-20211203190053403

订阅

image-20211203190900738

操作

image-20211203191811896

map :元素映射成新的元素

image-20211203191618748

flatmap :元素映射成流

image-20211203191646833

WebFlux执行流程与核心API

image-20211203192510567

BIO:阻塞方式

image-20211203192544088

NIO:非阻塞

image-20211203192656160

执行过程

image-20211203193429686

handle的底层源代码

image-20211203193355599

需要的API

image-20211203194413059

基于注解的编程模型

用户接口

image-20211203195302196

接口实现
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);
      }
}

image-20211203201242974

函数式编程模型

image-20211203202326148