野生程序员 野生程序员

让灵魂跟上脚步

目录
Spring 复习
/    

Spring 复习

IOC复习

什么是ioc

  • 控制翻转,把对象创建和对象之间的调用过程,交给Spring进行管理
  • 使用IOC的目的:为了降低耦合度

IOC的底层原理

  • xml解析、工厂模式、反射

IOC原理图

image-20210122140209449

image-20210122141119619

IOC接口

IOC思想是基于IOC容器完成,IOC容器底层就是工厂对象。

Spring提供了IOC容器实现两种方式:(两个接口)

BeanFactory:IOC的基本实现,是Spring内部使用的接口。不提供开发人员使用
  • 加载配置文件的时候不会去创建对象,在获取对象的时候才会去创建。
ApplicationContext是BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员使用
  • 加载配置文件的时候就会把配置文件里面的所有对象进行创建。

image-20210122202138591

IOC操作Bean管理(概念)

  • Spring创建对象
  • Spring注入属性

Bean管理操作的两种方式

  • 基于xml配置文件方式实现

在spring配置文件中,使用bean标签,标签里面添加对应的属性就可以实现对象的创建。

bean标签有很多的属性

id :唯一标识

class: 类全路径

name:现在用的很少,和id基本一个性质,但是可以添加特殊符号

创建对象的时候,默认也是执行的无参构造方法完成对象的创建

<!--配置User对象创建-->
<bean id="user" class="net.yscxy.spring5.User"/>
  • 基于xml方式注入属性

第一种注入方式:使用set方法进行注入

<bean id="book" class="net.yscxy.spring5.Book">
 <!--使用property进行属性注入-->
 <property name="banme" value="测试注入"/>
</bean>

第二种注入方式:使用有参构造进行注入

<!--有参构造注入属性-->
<bean id="order" class="net.yscxy.spring5.Order">
 <constructor-arg index="0" value="1"/>
 <constructor-arg index="1" value="测试订单"/>
</bean>

第三种注入方式:使用名称空间注入其实也是set方法进行注入

加入名称空间

xmlns:p="http://www.springframework.org/schema/p"
<!--使用名称空间进行注入-->
<bean id="order" class="net.yscxy.spring5.Order" p:id="123" p:name="测试"></bean>

分割线

IOC操作Bean管理-(FactoryBean)

1、Spring有两种类型的bean,一种是普通Bean,另外一种是工厂Bean

2、普通Bean:在配置文件中定义bean类型就是返回类型

3、工厂bean:在配置文件中定义bean类型可以返回的不一样

第一步:创建类,让这个类作为工厂bean实现接口FactoryBean

第二步:实现接口里面的方法,在实现方法中定义返回的bean类型

工厂模式就是为了不暴露创建对象的过程

package net.yscxy.spring5.factorybean;

import org.springframework.beans.factory.FactoryBean;

public class MyBean implements FactoryBean<User> {
    //定义返回bean
    @Override
    public User getObject() throws Exception {
        return new User("安其拉");
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

IOC操作Bean管理(Bean的作用域)

1、在Spring里面。可以设置bean实例是单实例还是多实例的

2、在Spring里面,默认是单实例的bean

//单实例测试
@Test
public void testuser() {
    //记载spring配置文件
    ApplicationContext context = new FileSystemXmlApplicationContext("bean03.xml");
    //获取配置创建的对象
    User user1= context.getBean("user", User.class);
    user1.setName("123");
    System.out.println(user1.toString());
    User user2= context.getBean("user", User.class);
    System.out.println(user2.toString());
}
//输出结果:
User{name='123'}
User{name='123'}

3、如何设置多实例(在bean标签里面有属性用于设置时多实例还是单实例-scope)scope="prototype"

//此时的输出 结果为下所示
User{name='123'}
User{name='null'}

如果设置的值为scope="prototype"那么就不是在加载Spring配置文件的时候创建对象,而是在调用getBean的时候创建对象,每次都是新建的一个实例。

IOC操作Bean管理(bean的生命周期)

1、通过构造器创建bean(无参构造)

2、为bean的属性设置值和对其他bean的引用(调用set方法)

-->把bean实例传递bean后置处理方法

3、调用bean的初始化方法(需要进行配置)

-->把bean实例传递bean后置处理方法

4、bean可以使用了(对象获取到了)

5、让容器关闭的时候,调用bean的销毁方法(需要进行配置销毁的方法)

<bean id="order" class="net.yscxy.spring5.bean.Orders" init-method="initMethod" destroy-method="destory">
    <property name="oname" value="手机" ></property>
</bean>

IOC操作Bean管理(xml自动装配)

1、根据指定装配的规则(属性名称或者属性类型)Spring自动将匹配的属性进行注入

<!--实现自动装配
bean标签属性autowire 配置自动装配
autowire属性常用两个值:
  byName根据属性名称注入,注入bean的id的值和类的属性的名称需要一样
  byType根据属性类型注入
-->
<bean id="emp" class="net.yscxy.spring5.autoWire.Emp" autowire="byType">

IOC操作Bean管理(外部属性文件)

1、直接配置数据库信息

2、通过引入外部的属性文件(记得引入名称空间)

image-20210311163122821

image-20210311163142202

IOC操作Bean管理(基于注解方式)

Spring 针对Bean管理中的创建对象提供注解

1、@Component

2、@Service

3、@Controller

4、@Respository

<!--开启组件扫描
1.如果扫描多个包,多个包使用逗号隔开
2.扫描包的上层目录
-->
<context:component-scan base-package="net.yscxy.spring5"></context:component-scan>

需要注意的细节问题

image-20210311172816292

基于注解方式实现属性注入

1、@AutoWired 根据属性类型进行自动装配

2、@Qualifier 根据属性名称进行注入,需要配合@AutoWired 自定义名称的时候

3、@Resource 根据类型注入,可以根据名称注入

4、@Value 注入普通类型属性

当然上面的写法还是没有完全脱离xml配置文件,我们也可以写一下配置文件类去进行替代,但是需要这样来进行加载配置类

image-20210313090905810

AOP概念

面向切面编程-不改变源代码,可以添加先功能

image-20210313091528743

AOP底层原理

底层使用动态代理

1、有接口情况 ——使用JDK动态代理

2、没有接口的情况——使用CGLIB

image-20210313092044925

package net.yscxy.spring5;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

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));
        int add = dao.add(1, 2);
        System.out.println(add);
    }
}

class UserDaoProxy implements InvocationHandler {
    private Object object;

    //把创建的谁的代理对象,需要把这个对象传过来
    public UserDaoProxy(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法之前
        System.out.println("方法执行之前" + method.getName() + "  传递的参数:" + Arrays.toString(args));
        //被增强的方法
        Object res = method.invoke(object, args);
        //方法之后执行
        System.out.println("方法执行之后执行..." + object.toString());
        return res;
    }
}

image-20210313092247419

AOP术语

1、连接点:类里面哪些方法可以被增强,这些方法称为连接点

2、切入点:实际被真增强的方法称为 、切入点

3、通知(增强):实际增强的逻辑部分称为通知

通知有多种类型:前置通知,后置通知、环绕通知、异常通知、最终通知(finally)

4、切面:是动作,把通知应用到切入点的过程

切入点表达式
  1. 切入点表达式的作用:知道那个类里面的哪个方法进行增强
  2. 语法结构:execution([权限修饰符] [返回类型] [类全路径] [方法名称] ([参数列表]))

image-20210313105824121

package net.yscxy.spring5.aopanno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

//增强类
@Aspect //表示要生成一个代理对象
@Component
public class UserProxy {
    @Before(value = "execution(* net.yscxy.spring5.aopanno.User.add(..))")
    public void before() {
        System.out.println("before...");
    }
    //最终通知
    @After(value = "execution(* net.yscxy.spring5.aopanno.User.add(..))")
    public void After() {
        System.out.println("After...");
    }
    //有异常的时候通知
    @AfterThrowing(value = "execution(* net.yscxy.spring5.aopanno.User.add(..))")
    public void AfterThrowing() {
        System.out.println("AfterThrowing...");
    }
    @AfterReturning(value = "execution(* net.yscxy.spring5.aopanno.User.add(..))")
    public void AfterReturning() {
        System.out.println("AfterReturning ...");
    }
    //环绕通知
    @Around(value = "execution(* net.yscxy.spring5.aopanno.User.add(..))")
    public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕之前...");
        proceedingJoinPoint.proceed();
        System.out.println("环绕之后...");
    }

}

执行顺序为:

环绕之前...
before...
add ....
环绕之后...
After...
AfterReturning ...

相同切入点抽取

//相同切入点抽取
@Pointcut(value = "execution(* net.yscxy.spring5.aopanno.User.add(..))")
public void pointdemo() {

}

@Before(value = "pointdemo()")
public void before() {
    System.out.println("before...");
}

有多个增强类多同一个方法进行增强,设置增强类优先级

  1. 在增强类上面添加注解@Order(数值类型),数字类型值越小,优先级越高

事物

事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个操作失败,那么都失败

事务四个特性ACID

1、原子性

2、一致性

3、隔离性

4、持久性

事务一般加到Service层,且有两种方式,一种是编程方式,一种是声明式

@Tyansactional(),直接写在类上

propagation:事务的传播行为

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

3、ioslation: 隔离级别

事务有特性成为隔离性,多事务操作之间不会产生影响。不考虑隔离性产生很多问题

(1)脏读、不可重复读、虚(幻)读

脏读:一个未提交事务读取到另一个未提交事务的数据

image-20210313170059134

不可重复读 :一个未提交事务读取到另一个提交事务修改数据

image-20210313170445921

虚读:一个未提交事务读取到另一个提交事务添加数据

隔离级别配置参数:mysql默认-可重复读

image-20210313170706380

4、timeout:超时时间

(1)事务需要在一定时间内进行提交,如果不提交进行回滚

(2)默认值时-1,设置时间以秒未单位进行计算

5、readOnly:是否只读

(1)读,只能查询,默认未false

6、rollbackFor:回滚

(1)设置出啊先哪些异常进行事务回滚

7、noRollbackFor:不回滚

(1)设置出现哪些异常不进行事务回滚

事务的传播行为

image-20210313165139406

Spring5新功能

(1)Spring5整合Log4j2

(2)@Nullable,可以使用在方法上(返回值可为空),参数,属性,

(3)支持函数式表达式

image-20210313173458931

Spring5框架新功能(WebFlux)

1、介绍

(1)是Spring5添加的新模块,用于Web开发的,功能和SpringMvc类似,Webflux使用当前一种比较流程像饮食编程出现的框架。

(2)使用传统的Web框架比如SpringMvc,这些基于Servlet容器,Webflux是哟中异步非阻塞的框架,异步非阻塞的框架在Servlet3.1以后才支持,核心是基于Reactor的相关API实现的。

(3)异步和同步针对调用者,调用者发送请求

2、响应式编程
  1. 什么是响应式编程:

响应式编程是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。

image-20210314083635963

  1. Java以及之前的版本

提供得到观察者模式两个类:Observer和Observable

package net.yscxy.demoreactor8.reactor8;

import java.util.Observable;

public class ObserverDemo extends Observable {
    public static void main(String[] args) {
        ObserverDemo observerDemo = new ObserverDemo();
        //添加观察者
        observerDemo.addObserver((o, arg) -> {
            System.out.println("发生变化");
        });
        observerDemo.addObserver((o, arg) -> {
            System.out.println("手动被观察者通知,准备改变");
        });
        observerDemo.setChanged();//数据变化
        observerDemo.notifyObservers();//通知
    }
}
  1. 响应式编程(Reactor实现)

(1)响应式编程操作中,Reactor是满足Reactive规饭框架

(2)Reactor有两个核心类,Mono和Glux,这两个类实现接口Publisher,提供丰富操作符,Flux对象实现发布者,返回N个元素;Mono实现翻发布者,返回0或者1个元素

(3)Flux和Mono都是数据流的发布者,使用Flux和Mono都可以发出三种信号:元素值,错误信号,完成信号,错误信号 和完成信号,都代表终止信号,终止信号告诉订阅者数据流结束了。

image-20210314091328538

最后挂几个链接咯感兴趣可以瞧瞧的:

神奇工作室

神奇工作室


标题:Spring 复习
作者:野生程序员
地址:http://yscxy.net/articles/2021/03/15/1615777093569.html