Spring之后处理器

news2024/10/4 1:22:29

目录

一:概述

二:案例演示

三:Bean的后处理器----BeanPostProcessor

案例:对Bean方法进行执行时间日志增强

四:Spring ioc整体流程总结


一:概述

              Spring的后处理器是Spring对外开发的重要扩展点、允许我们介入到Bean的整个实例化流程中来, 以达到动态注册 BeanDefinition, 动态修改BeanDefinition, 以及动态修改Bean的作用。Spring主要有两种后处理器:

  • BeanFactoryPostProcessor:Bean工厂后处理器, 在BeanDefinitionMap填充完毕, Bean实例化之前执行;

  • BeanPostProcessor:Bean后处理器, 一般在Bean实例化之后, 填充到单例池singletonObjects之前执行。

              Bean工厂后处理器-BeanFactoryPostProcessor BeanFactoryPostProcessor是一个接口规范, 实现了该接口的类只要交由Spring容器管理的话, 那么Spring就会回调该接口的方法, 用于对BeanDefinition注册和修改的功能。

        BeanFactoryPostProcessor定义如下:

public interface BeanFactoryPostProcessor{
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) ;
}

二:案例演示

①:注册BeanDefinition

1.编写MyBeanFactoryPostProcessor类,实现BeanFactoryPostProcessor接口,并实现接口方法

package com.tangyuan.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;

/**
 * @author 唐渊
 * @create  2022-11-25 16:15
 */
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("beanDefinitionMap填充完毕后回调该方法");
        //不在主xml文件中进行配置bean
        //动态注册Beandifinition
          BeanDefinition beanDefinition=new RootBeanDefinition();
          beanDefinition.setBeanClassName("com.tangyuan.dao.impl.PeresonDaoImpl");                                     System.out.println(beanFactory);                       //org.springframework.beans.factory.support.DefaultListableBeanFactory@737996a0: defining beans
        //强转成DefaultListableBeanFactory
        DefaultListableBeanFactory defaultListableBeanFactory= (DefaultListableBeanFactory) beanFactory;
        defaultListableBeanFactory.registerBeanDefinition("PersonDao",beanDefinition);

    }
}

2.测试

//创建ApplicationContext,加载配置文件,实例化容器
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
PeresonDao bean = applicationContext.getBean(PeresonDao.class);
System.out.println(bean);//com.tangyuan.dao.impl.PeresonDaoImpl@6ddf90b0

②:注册BeanDefinition

            Spring提供了一个BeanFactoryPostProcessor的子接BeanDefinitionRegistryPostProcessor专门用于注册BeanDefinition操作

public class MyBeanFactoryPostProcessor2 implements BeanDefinitionRegistryPostProcessor{

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException{}

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException{

BeanDefinition beanDefinition=new RootBeanDefinition() ;
beanDefinition.setBeanClassName("com.tangyuan.dao.UserDaoImp12");

beanDefinitionRegistry.registerBeanDefinition("userDao2",beanDefinition) ;

}
}

案例演示:

        1.编写MyBeanDefinitionRegistryPostProcessor类,实现BeanDefinitionRegistryPostProcessor接口,并实现接口方法

package com.tangyuan.processor;

import com.alibaba.druid.support.spring.stat.SpringStatUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;

/**
 * @author 唐渊
 * @create  2022-11-28 10:21
 */
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法");
        //向容器当中注册BeanDefinition
        BeanDefinition beanDefinition=new RootBeanDefinition();
        beanDefinition.setBeanClassName("com.tangyuan.dao.impl.PeresonDaoImpl");
         beanDefinitionRegistry.registerBeanDefinition("PersonDao",beanDefinition);

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法");
    }
}

2.将MyBeanDefinitionRegistryPostProcessor类在xml文件中进行配置

<bean class="com.tangyuan.processor.MyBeanDefinitionRegistryPostProcessor"></bean>

3.测试

//创建ApplicationContext,加载配置文件,实例化容器
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
PeresonDao bean = applicationContext.getBean(PeresonDao.class);
System.out.println(bean);//com.tangyuan.dao.impl.PeresonDaoImpl@5a8e6209

ps:方法的执行顺序

1.MyBeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
2.MyBeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法
3.MyBeanFactoryPostProcessor的postProcessBeanFactory方法

③:使用Spring的BeanFactoryPostProcessor扩展点完成自定义注解扫描

要求如下:

  • 自定义@MyComponent注解, 使用在类上;

  • 使用资料中提供好的包扫描器工具BaseClassScanUtils完成指定包的类扫描;

  • 自定义BeanFactoryPostProcessor完成注解@MyComponent的解析, 解析后最终被Spring管理。

1.创建一个OtherBean类,并定义@MyComponent注解

package com.tangyuan.beans;

import com.tangyuan.anno.MyComponent;

/**
 * @author 唐渊
 * @create  2022-11-28 15:34
 */
@MyComponent("OtherBean")
public class OtherBean {
}
package com.tangyuan.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author 唐渊
 * @create  2022-11-28 15:35
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponent {
    String value();
}

2.BaseClassScanUtils 帮助类编写

package com.tangyuan.utils;

import com.tangyuan.anno.MyComponent;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;

import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BaseClassScanUtils {

    //设置资源规则
    private static final String RESOURCE_PATTERN = "/**/*.class";

    public static Map<String, Class> scanMyComponentAnnotation(String basePackage) {

        //创建容器存储使用了指定注解的Bean字节码对象
        Map<String, Class> annotationClassMap = new HashMap<String, Class>();

        //spring工具类,可以获取指定路径下的全部类
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        try {
            String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    ClassUtils.convertClassNameToResourcePath(basePackage) + RESOURCE_PATTERN;
            Resource[] resources = resourcePatternResolver.getResources(pattern);
            //MetadataReader 的工厂类
            MetadataReaderFactory refractory = new CachingMetadataReaderFactory(resourcePatternResolver);
            for (Resource resource : resources) {
                //用于读取类信息
                MetadataReader reader = refractory.getMetadataReader(resource);
                //扫描到的class
                String classname = reader.getClassMetadata().getClassName();
                Class<?> clazz = Class.forName(classname);
                //判断是否属于指定的注解类型
                if(clazz.isAnnotationPresent(MyComponent.class)){
                    //获得注解对象
                    MyComponent annotation = clazz.getAnnotation(MyComponent.class);
                    //获得属value属性值
                    String beanName = annotation.value();
                    //判断是否为""
                    if(beanName!=null&&!beanName.equals("")){
                        //存储到Map中去
                        annotationClassMap.put(beanName,clazz);
                        continue;
                    }

                    //如果没有为"",那就把当前类的类名作为beanName
                    annotationClassMap.put(clazz.getSimpleName(),clazz);

                }
            }
        } catch (Exception exception) {
        }

        return annotationClassMap;
    }

    public static void main(String[] args) {
        Map<String, Class> stringClassMap = scanMyComponentAnnotation("com.tangyuan");
        System.out.println(stringClassMap);
    }
}

3.编写MyComponentBeanFactoryPostProcessor类,并实现BeanDefinitionRegistryPostProcessor接口

package com.tangyuan.processor;

import com.tangyuan.utils.BaseClassScanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;

import java.util.Map;

/**
 * @author 唐渊
 * @create  2022-11-28 15:45
 */
public class MyComponentBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        //通过扫描工具去扫描指定包及其包下的所有类,收集使用@MyComponent注解的类
        Map<String, Class> map = BaseClassScanUtils.scanMyComponentAnnotation(
                "com.tangyuan"
        );
        //循环遍历,组装BeanDefinition进行注册
        map.forEach((beanName,clazz)->{
       //获取BeanClassName
            String name = clazz.getName();//com.tangyuan.beans.OtherBean
        //创建BeanDefinition
            BeanDefinition beanDefinition=new RootBeanDefinition();
            beanDefinition.setBeanClassName(name);
           //注册
            beanDefinitionRegistry.registerBeanDefinition(name,beanDefinition);


        });

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}

4.在xml文件编写MyComponentBeanFactoryPostProcessor类的bean

<bean class="com.tangyuan.processor.MyComponentBeanFactoryPostProcessor"></bean>

5.测试

OtherBean bean1 = applicationContext.getBean(OtherBean.class);
System.out.println(bean1);//com.tangyuan.beans.OtherBean@1877ab81

6.编写一个BookBean类,并实现@MyComponent注解

package com.tangyuan.beans;

import com.tangyuan.anno.MyComponent;
import org.springframework.stereotype.Component;

/**
 * @author 唐渊
 * @create  2022-11-28 16:09
 */
@MyComponent("BookBean")
public class BookBean {
}

7.再次测试

//创建ApplicationContext,加载配置文件,实例化容器
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
BookBean bean2 = applicationContext.getBean(BookBean.class);
System.out.println(bean2);//com.tangyuan.beans.BookBean@1877ab81

三:Bean的后处理器----BeanPostProcessor

                   Bean被实例化后, 到最终缓存到名为singletonObjects单例池之前, 中间会经过Bean的初始化过程, 例如:属性的 填充、初始方法init的执行等, 其中有一个对外进行扩展的点BeanPostProcessor,我们称为Bean后处理。跟上面的 Bean工厂后处理器相似, 它也是一个接口, 实现了该接口并被容器管理的BeanPostProcessor, 会在流程节点上被 Spring自动调用。

BeanPostProcessor的接口定义如下:

public interface BeanPostProcessor{
@Nullable
//在属性注入完毕, init初始化方法执行之前被回调
default Object postProcesBeforeInitialization(Object bean, String bean Name)throws BeansException{
return bean;
}

//在初始化方法执行之后, 被添加到单例池singletonObjects之前被回调
@Nullable
default Object postProcessAfterInitialization(Object bean, String bean Name) throws BeansException{
return bean;
}
}

案例:对Bean方法进行执行时间日志增强

要求如下:

  • Bean的方法执行之前控制台打印当前时间;

  • Bean的方法执行之后控制台打印当前时间。

分析:

  • 对方法进行增强主要就是代理设计模式和包装设计模式;

  • 由于Bean方法不确定, 所以使用动态代理在运行期间执行增强操作;

  • 在Bean实例创建完毕后, 进入到单例池之前, 使用Proxy代替真是的目标Bean

思路:编写BeanPostProcessor, 增强逻辑编写在after方法中

public Object post Process After Initialization(Object bean,String beanName) throws BeansException{
//Bean进行动态代理,返回的是Proxy代理对象
Object proxy Bean=Proxy.newProxyInstance(bean.getClass() .getClassLoader() ,
bean.getClass() .getInterfaces() ,
(Object proxy, Method method,Object[] args) ->{
long start=System.currentTimeMillis() ;
system.out.println("开始时间:"+new Date(start) ) ;
//执行目标方法BIN
Object result=method.invoke(bean,args) ;
long end=System.currentTimeMillis() ;
System.out.println("结束时间:"+new Date(end) ) ;
return result;
});
//返回代理对象
return proxy Bean;
}

实现代码如下:

1.编写一个TimeLogBeanPostProcessor类,接口BeanPostProcessor实现,方法也实现

package com.tangyuan.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

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

/**
 * @author 唐渊
 * @create  2022-11-29 9:48
 */
public class TimeLogBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
          //使用动态代理对目标Bean进行增强,返回proxy对象,进而存储到单例池singletonObjects中
            Object beanProxy= Proxy.newProxyInstance(
                bean.getClass().getClassLoader(),
                bean.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //1.输出开始时间
                        System.out.println("方法:"+method.getName()+"-开始时间:"+new Date());
                        //2.执行目标方法
                        Object invoke = method.invoke(bean, args);
                        //3.输出结束时间
                        System.out.println("方法:"+method.getName()+"-结束时间:"+new Date());
                        return invoke;
                    }
                }
        );

        return beanProxy;
    }
}

2.在xml文件上完成对TimeLogBeanPostProcessor类的配置

<bean class="com.tangyuan.processor.TimeLogBeanPostProcessor"></bean>

3.编写方法

package com.tangyuan.dao;

/**
 * @author 唐渊
 * @create  2022-11-20 9:29
 */
public interface UserDao {
    void show();
}
package com.tangyuan.dao.impl;

import com.tangyuan.dao.UserDao;
import org.springframework.beans.factory.InitializingBean;

/**
 * @author 唐渊
 * @create  2022-11-20 9:29
 */
public class UserDaoImpl implements UserDao , InitializingBean {
    public UserDaoImpl() {
        System.out.println("UserDao实例化");
    }

    public void init(){
        System.out.println("init初始化方法执行");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("属性设置之后执行~~~~");
    }

    @Override
    public void show() {//ctrl+Alt+t
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("show.....");
    }
}

4.测试

//创建ApplicationContext,加载配置文件,实例化容器
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao dao = (UserDao) applicationContext.getBean("userDao");
dao.show();
方法:show-开始时间:Tue Nov 29 10:21:31 GMT+08:00 2022
show.....
方法:show-结束时间:Tue Nov 29 10:21:31 GMT+08:00 2022

四:Spring ioc整体流程总结

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/136875.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

量子计算机是什么?量子计算机和传统计算机之间有什么区别?

1.突破1000量子比特大关&#xff01; 2022年11月9日的IBM年度量子峰会上&#xff0c;IBM宣布了Osprey在量子硬件和软件方面取得的突破性进展&#xff0c;同时推出了“鱼鹰”&#xff08;Osprey&#xff09;芯片。“鱼鹰”是全球迄今为止量子比特最多的量子计算机&#xff0c;而…

软考初级信息处理

软考初级信息处理技术员还是比较简单的&#xff0c;只要多刷题&#xff0c;实操也很重要的&#xff01;备考时间讲究高效哦&#xff01; 1、考试安排&#xff1a; 2、关于信处的考点分析&#xff1a; 上午考试&#xff1a; 下午考试&#xff1a; 3、信处如何备考&#xff1a;…

从spark WordCount demo中学习算子:map、flatMap、reduceByKey

文章目录spark map和flatMap应用&#xff1a;Word CountreduceByKey的用法spark map和flatMap val rdd sc.parallelize(List("coffee panda","happy panda","happiest panda party"))&#xff08;1&#xff09;map rdd.map(_.split(" &q…

windows terminal 还是 cmder ?

前景提要 windows terminal自带的没有tab命令自动补全, cmd的自动补全垃圾; cmder虽然有自动补全, 但是界面管理不太行; 而且比较复杂&#xff1b;只想要其UI和路径换行显示; windows terminal 应用商城或https://github.com/microsoft/terminal 下载页 https://github.com/mic…

【算法刷题】哈希表题型及方法归纳

哈希表特点 常见的三种哈希结构&#xff1a; 1、数组&#xff1a;操作简单&#xff0c;方便快捷&#xff0c;但不适于进行一些更复杂的操作。 注&#xff1a;适用于用set或map的情景&#xff1a;&#xff08;1&#xff09;当数组大小受限&#xff1b;&#xff08;2&#xff0…

powerquery 连接 postgresql

1下载安装postgresql的驱动器 https://pan.baidu.com/s/1ii9PudUs9WL_clP7Ub647Q 提取码&#xff1a;hm6g 2 安装配置odbc 2.1打开控制面板 – 选择管理工具 2.2选择ODBC数据源(64位) 2.3控制面板搜索数据源-单击添加 选择postgresql unicode 2.4配置数据源信息 3.通过e…

einsum 理解

本文是参考以下两篇文章&#xff0c;再结合我自己的经验完成的&#xff1a; 文章一&#xff1a;https://zhuanlan.zhihu.com/p/358417772 文章二&#xff1a;https://zhuanlan.zhihu.com/p/27739282 Einsum介绍&#xff1a; 给定矩阵A 和矩阵B &#xff08;在Python中也可以说是…

【PCB专题】PCB板卡上的UL标识是什么?

PCB行业中重要的认证之一是UL认证。在网上直接搜索UL会出现很多与防火、安全、保险相关的词汇出现。

开发板测试手册——USB 4G 模块、GPS 定位功能操作步骤详解(3)

目录 4 USB 4G 模块测试 41 4.1 网络功能测试 42 4.2 短信功能测试 43 4.3 GPS 定位功能测试 44 4.4 通话功能测试 45 4.5 测试程序编译 46 5 USB 网口模块测试 47 前 言 本指导文档适用开发环境: Windows 开发环境: Windows 7 64bit 、Windows 10 64bit Linux 开…

C语言进阶内功修炼——深度剖析数据在内存中的存储

&#x1f412;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;别人可以拷贝我的模式&#xff0c;但不能拷贝我不断往前的激情 目录 &#x1f680;1. 数据类型介绍 &#x1f307;1.1 类型的基本归类&#xff1a; &#x1f680;2. 整形在内存中的存储 &am…

Three.js学习(一)three.js的一些基本操作

文章目录1.鼠标操作三维场景旋转、移动和缩放2.场景中添加新的三维图形3.设置材质效果4.光源效果1.鼠标操作三维场景旋转、移动和缩放 使用THREE的OrbitControls控件&#xff0c;可以实现鼠标控制三维图形的操作。主要是通过监听鼠标操作&#xff0c;控制相机的三维参数。 imp…

在线问诊呈爆发式增长,聚合支付分账如何助力互联网医疗平台加速发展?

&#xff08;图源:pexels网站&#xff09; 随着疫情的放开&#xff0c;人们问诊需求快速上涨&#xff0c;由于医院服务的压力激增&#xff0c;线上问诊成为了不少人替代去医院的有效手段&#xff0c;甚至于线上问诊开始出现了爆发式增长。但是在互联网医疗平台的发展过程中&am…

C语言进阶——数据的存储

目录 一. 数据类型 二. 整形在内存中的存储 1.原码、反码、补码 2.大小端 三. 浮点型在内存中的存储 存储 取出 一. 数据类型 在前面&#xff0c;我们已经学过一些基本的内置类型 char——字符数据类型 short——短整型 int——整形 long——长整形 long…

电路方案分析(十四)汽车电动座椅参考方案设计(H桥,高低边驱动器设计)

汽车电动座椅参考方案设计 tips&#xff1a;TI设计方案参考分析&#xff1a;TI Designs&#xff1a;TIDA-020008 双向和单向电机驱动器的电机驱动应用&#xff08;如汽车电动座椅&#xff09;的驱动和控制电路。它演示了如何驱动具有小电路板尺寸、高度可靠性和完整诊断功能的…

第二章 linux常用指令

第二章 linux常用指令一、ls指令&#xff1a;查看目录内容1、作用2、语法3、示例二、pwd命令&#xff1a;查看当前位置1、作用2、语法3、示例三、cd 指令&#xff1a;进入1、作用2、语法3、常用变型四、touch指令&#xff1a;创建文件1、作用2、语法3、常用选项五、mkdir指令&a…

12月VR大数据:兼2022全年VR硬件和应用汇总

Hello大家好&#xff0c;每月一期的VR内容/硬件大数据统计又和大家见面了。 想了解VR软硬件行情么&#xff1f;关注这里就对了。我们会统计Steam平台的用户及内容等数据&#xff0c;每月初准时为你推送&#xff0c;不要错过喔&#xff01;本数据报告包含&#xff1a;Steam VR硬…

excel查找技巧:单个函数在区间查找中的应用解析

区间取值的问题&#xff0c;在我们日常工作中经常会遇到&#xff0c;比如&#xff1a;销售提成、等级评定、生产标准核定、绩效考核等等&#xff0c;都属于此类问题&#xff0c;今天就给大家介绍几种常用的方式方法&#xff0c;旨在丰富大家知识面的同时&#xff0c;也可以对函…

JavaScript 变量

文章目录JavaScript 变量JavaScript 变量JavaScript 数据类型声明&#xff08;创建&#xff09; JavaScript 变量一条语句&#xff0c;多个变量重新声明 JavaScript 变量JavaScript 算数JavaScript 变量 变量是用于存储信息的"容器"。 实例 var x5; var y6; var zx…

BlocProvider add数据流程

我们看看往bloc中添加数据流程&#xff0c;以demo为例 void _incrementCounter() {_counter;BlocProvider.of<TestBloc>(context).add(LoadTestEvent(_counter));} 我们调用了BlocProvider获取对应的Bloc &#xff0c;然后调用他的add方法 void add(Event event) {asser…

【华为重启门】华为/荣耀手机一直自动重启原因解决方案(荣耀V10)

文章目录1.问题描述2.分析原因3.解决方案4.实际操作1.问题描述 荣耀V10&#xff0c;莫名其妙的、无规律的死机重启。 一开始是重启后进入紧急备份&#xff0c;无法正常开机。 之后莫名其妙可以正常开机了&#xff0c;但是总是会重启。 2.分析原因 不搜不知道&#xff0c;一…