首页 > 其他分享 >2_Bean的生命周期和常见的后处理器

2_Bean的生命周期和常见的后处理器

时间:2024-06-10 13:45:17浏览次数:11  
标签:生命周期 System class Bean 处理器 context println public out

1. Spring Bean生命周期各个阶段

首先编写一个Bean:

@Component
public class LifeCycleBean {
    public LifeCycleBean(){
        System.out.println("Bean 构造");
    }

    @Autowired
    public void autowire(@Value("${JAVA_HOME}")String javaHome){
        System.out.println("Bean 依赖注入:"+javaHome);
    }

    @PostConstruct
    public void init(){
        System.out.println("Bean 初始化");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("Bean 被销毁");
    }
}

编写主方法测试代码:

@SpringBootApplication
public class A03Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(A03Application.class, args);
        context.close();

    }
}
Bean 构造
Bean 依赖注入:/opt/development_tools/jdk21/jdk-21.0.3
Bean 初始化
2024-06-08T17:06:10.657+08:00  INFO 30992 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 9000 (http) with context path ''
2024-06-08T17:06:10.672+08:00  INFO 30992 --- [           main] com.cherry.a03.A03Application            : Started A03Application in 2.645 seconds (process running for 3.334)
Bean 被销毁

我们发现。完整的Bean生命周期是:

  1. 通过构造方法实例化Bean对象
  2. 对Bean对象进行依赖注入(该Bean 可能会引入其它的Bean对象)
  3. 对Bean对象进行初始化
  4. Bean对象随着容器的销毁而销毁(当然是在容器销毁前而销毁)

由于默认的而BeanFactory对于Bean管理只有核心的功能,而对Bean功能的怎增强则是通过Bean后处理器来完成的,我破门可以使用不同的Bean后处理器针对Bean不同的生命周期进行扩展。这里举一个简单的例子:

@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if(beanName.equals("lifeCycleBean")){
            System.out.println("<<<销毁之前执行 如 @PreDestroy<<<");
        }
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if(beanName.equals("lifeCycleBean")){
            System.out.println("<<<实例化之前执行,这里返回的对象会替换掉原来的bean  <<<");
        }
        return null;
    }


    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            System.out.println("<<<实例化之后执行,这里返回false会跳过依赖注入  <<<");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if(beanName.equals("lifeCycleBean")){
            System.out.println("<<<依赖注入阶段执行,如@Autowired, @AValue, @Resource <<<");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("lifeCycleBean")){
            System.out.println("<<<初始化Bean之前执行,这里返回的对象会替换掉原来的Bean对象,如@POsrConstruct, @ConfigurationProperties <<<");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("lifeCycleBean")){
            System.out.println("<<< 初始化之后执行,这里返回的对象会替换掉原来的Bean,如代理增强<<<");
        }
        return bean;
    }
}

运行:

<<<实例化之前执行,这里返回的对象会替换掉原来的bean  <<<
Bean 构造
<<<实例化之后执行,这里返回false会跳过依赖注入  <<<
<<<依赖注入阶段执行,如@Autowired, @AValue, @Resource <<<
Bean 依赖注入:/opt/development_tools/jdk21/jdk-21.0.3
<<<初始化Bean之前执行,这里返回的对象会替换掉原来的Bean对象,如@POsrConstruct, @ConfigurationProperties <<<
Bean 初始化
<<< 初始化之后执行,这里返回的对象会替换掉原来的Bean,如代理增强<<<
2024-06-08T17:31:34.698+08:00  INFO 31600 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 9000 (http) with context path ''
2024-06-08T17:31:34.713+08:00  INFO 31600 --- [           main] com.cherry.a03.A03Application            : Started A03Application in 2.913 seconds (process running for 3.471)
<<<销毁之前执行 如 @PreDestroy<<<
Bean 被销毁

2. 模板设计模式

模板设计模式就是在不改变原有代码的基础上,提高现有代码的扩展能力。

模拟Spring容器编写一个BeanFactory

public class TestMethodTemplate {
    public static void main(String[] args) {
        MyBeanFactory beanFactory = new MyBeanFactory();
        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public void inject(Object bean) {
                System.out.println("解析 @Autowired");
            }
        });

        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public void inject(Object bean) {
                System.out.println("解析 @Resource");
            }
        });

        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public void inject(Object bean) {
                System.out.println("解析 @Value");
            }
        });
        beanFactory.getBean();
    }

    static class MyBeanFactory{
        public Object getBean(){
            Object bean = new Object();
            System.out.println("构造: "+bean);
            System.out.println("依赖注入: "+bean);  //@Autowired注解解析
            for(BeanPostProcessor processor:processors){
                processor.inject(bean);
            }
            System.out.println("初始化: "+bean);
            return bean;
        }

        // 存储bean后处理器
        private List<BeanPostProcessor> processors = new ArrayList<>();

        // 想后处理器集合中添加后处理器
        public void addBeanPostProcessor(BeanPostProcessor processor){
            processors.add(processor);
        }

    }

    static interface BeanPostProcessor{
        public void inject(Object bean);   // 对依赖注入阶段的功能进行扩展
    }
}
构造: java.lang.Object@5f184fc6
依赖注入: java.lang.Object@5f184fc6
解析 @Autowired
解析 @Resource
解析 @Value
初始化: java.lang.Object@5f184fc6

Process finished with exit code 0

将不确定的逻辑操作抽象成接口,将来在特定的时机调用来调用抽象方法。

3. 常见的Bean后处理器

首先定义几个Bean对象:

Bean1:

public class Bean1 {
    private Bean2 bean2;
    private Bean3 bean3;
    private String home;

    @Autowired
    public void setBean2(Bean2 bean2){
        System.out.println("@Autowired 生效:"+bean2);
        this.bean2 = bean2;
    }

    @Resource
    public void setBean3(Bean3 bean3){
        System.out.println("@Autowired 生效:"+bean3);
        this.bean3 = bean3;
    }

    @Autowired
    public void setHome(@Value("${JAVA_HOME}")String home){
        System.out.println("@Value 生效:"+home);
        this.home = home;
    }

    @PostConstruct
    public void init(){
        System.out.println("@PostConstruct 生效");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("@PreDestroy 生效");
    }

    @Override
    public String toString() {
        return "Bean1{" +
                "bean2=" + bean2 +
                ", bean3=" + bean3 +
                ", home='" + home + '\'' +
                '}';
    }
}

Bean2:

public class Bean2 {}

Bean3:

public class Bean3 {}

Bean4:

/**
 *java.home=
 * java.version=
 */
@ConfigurationProperties(prefix = "java")
public class Bean4 {
    private String home;
    private String version;

    public String getHome() {
        return home;
    }

    public void setHome(String home) {
        this.home = home;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    @Override
    public String toString() {
        return "Bean4{" +
                "home='" + home + '\'' +
                ", version='" + version + '\'' +
                '}';
    }
}

主程序:

@SpringBootApplication
public class A04Application {
    public static void main(String[] args) {
        // GenericApplicationContext是一个比较容器,它并没有添加额外的bean处理器
        GenericApplicationContext context = new GenericApplicationContext();
        // 想容器中注册三个bean
        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);
        context.registerBean("bean4",Bean4.class);

        // 添加一个解析@Autowired和@Value注解的后处理器
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        // 添加一个协助@Value值获取的后处理器,一般配合AutowiredAnnotationBeanPostProcessor后处理器使用
        context.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        // 添加一个解析@Resource,@PostConstruct,@PreDestroy注解的后处理器
        context.registerBean(CommonAnnotationBeanPostProcessor.class);
        // 添加对@ConfigurationProperties注解解析的后处理器
        ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory());
        //初始化容器--执行beanFactory后处理器,添加bean后处理器,初始化所有单例
        context.refresh();
        System.out.println(context.getBean(Bean4.class));
        //销毁容器
        context.close();
    }
}

运行结果如下:

@Autowired 生效:com.cherry.a04.Bean3@77167fb7
@Autowired 生效:com.cherry.a04.Bean2@2f112965
@Value 生效:/opt/development_tools/jdk21/jdk-21.0.3
@PostConstruct 生效
Bean4{home='/usr/lib/jvm/jdk-21-oracle-x64', version='21.0.3'}
@PreDestroy 生效

关于Bean后处理器 AutowiredAnnotationBeanPostProcessor 的运行分析:

编写如下代码:

public class DigInAutowired {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        beanFactory.registerSingleton("bean2", Bean2.class);
        beanFactory.registerSingleton("bean3", Bean3.class);
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        // 1.创建一个后处理器对象
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);
        Bean1 bean1 = new Bean1();
        processor.postProcessProperties(null,bean1,"bean1"); // 执行依赖注入@Autowired@Value
        System.out.println(bean1);
    }
}

debug进入到postProcessProperties方法中去:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // 首先找到有没有加@Autowired注解的属性,方法,找到后封装到 InjectionMetadata 中
    InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);
        try {
            //通过反射给属性赋值,set方法反射调用等
            metadata.inject(bean, beanName, pvs);
            return pvs;
        } catch (BeanCreationException var6) {
            BeanCreationException ex = var6;
            throw ex;
        } catch (Throwable var7) {
            Throwable ex = var7;
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
        }
    }

除此之外我们还可以使用反射的机制手动获取@Autowird和@Value注解上的信息:

public class DigInAutowired {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2", Bean2.class);
        beanFactory.registerSingleton("bean3", Bean3.class);
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        // 1.创建一个后处理器对象
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);
        Bean1 bean1 = new Bean1();
//        processor.postProcessProperties(null,bean1,"bean1"); // 执行依赖注入@Autowired@Value
//        System.out.println(bean1);
        Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Bean1.class);
        findAutowiringMetadata.setAccessible(true);
        //反射调用该方法:获取bean1上加了@Autowired和@Value注解上的信息,包括成员变量和方法参数
        Object injectionMetaData = (InjectionMetadata)findAutowiringMetadata.invoke(processor,"bean1", Bean1.class, null);
        System.out.println(injectionMetaData);
    }
}

4. 常见工厂后处理器

BeanFactory后处理器的作用:为BeanFactory提供扩展。

例如:

首先编写如下Bean代码:

Config:

@Configuration
@ComponentScan("com.cherry.a05.component")
public class Config {
    private Bean1 bean1;
    @Bean
    public Bean1 bean1(){
        return new Bean1();
    }
}

Bean1:

@Component
public class Bean1 {}

编写主方法查看此时能否获取Bean对象

public class A05Application {
    private static final Logger logger = LoggerFactory.getLogger(A05Application.class);
    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("config",Config.class);
        context.refresh();  //初始化容器
        for(String name:context.getBeanDefinitionNames()){
            System.out.println(name);
        }
    }
}
config

我们发现只有我们手动加入的bean,而组建扫描并未生效,因此被@Bean注解的方法也未加入到容器中。

因此我们们需要加入一个可以解析@@ComponentScan注解信息的bean工厂后处理器:

public class A05Application {
    private static final Logger logger = LoggerFactory.getLogger(A05Application.class);
    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean(ConfigurationClassPostProcessor.class);
        // 扫描mybatias的Mapper接口,并将这些就接口加入到容器中
        context.registerBean(MapperScannerConfigurer.class);
        context.registerBean("config",Config.class);
        context.refresh();  //初始化容器
        for(String name:context.getBeanDefinitionNames()){
            System.out.println(name);
        }
    }
}

此时再次运行:

config
bean2
bean3
bean4
bean1

ConfigurationClassPostProcessor处理器支持对@ComponentScan,,@Bean,@Import,@ImportResource 注解的解析

5. 工厂后处理器的模拟实现

5.1 组件扫描

public class A06ApplicationTest {
    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();
        //查找类上有没有加@ComponentScan注解
        ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
        if(componentScan != null){
            //获取注解上的属性(包路径)
            for (String p : componentScan.basePackages()) {
//                System.out.println(p);  // com.cherry.a05.component
                // 修改包名转为路径 --> 子包下的所有的类
                String packagePath = "classpath*:"+p.replace(".","/")+"/**/*.class";
                // System.out.println(packagePath);
                CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
                Resource[] resources = context.getResources(packagePath);
                for(Resource res:resources){
                    // System.out.println(res);
                    MetadataReader reader = factory.getMetadataReader(res);
                    System.out.println(reader.getClassMetadata().getClassName());
                    // 判断是否加入了@Component
                    System.out.println("是否加了@Component: "+reader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));
                    System.out.println("是否加了@Component及其派生注解: "+reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));

                    if(reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()) ||
                        reader.getAnnotationMetadata().hasAnnotation(Component.class.getName())){
                        // 创建一个BeanDefinition
                        AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();
                        // 为BeanDefinition生成Bean Name
                        AnnotationBeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
                        String beanName = beanNameGenerator.generateBeanName(bd, context.getDefaultListableBeanFactory());
                        // 将BeanDefinition加入到BeanFactory中
                        context.getDefaultListableBeanFactory().registerBeanDefinition(beanName, bd);
                    }
                }
            }
        }

        context.refresh();
        System.out.println("===========");
        for(String name:context.getBeanDefinitionNames()){
            System.out.println(name);
        }
    }
}

运行结果如下:

com.cherry.a05.component.Bean2
是否加了@Component: true
是否加了@Component及其派生注解: false
com.cherry.a05.component.Bean3
是否加了@Component: true
是否加了@Component及其派生注解: false
com.cherry.a05.component.Bean4
是否加了@Component: false
是否加了@Component及其派生注解: true
09:19:43.994 [main] INFO com.cherry.a05.component.Bean2 -- 我被spring容器管理了...
09:19:44.011 [main] INFO com.cherry.a05.component.Bean3 -- 我被spring容器管理了...
09:19:44.012 [main] INFO com.cherry.a05.component.Bean4 -- 我被spring容器管理了...
===========
bean2
bean3
bean4

Process finished with exit code 0

把上述的组件扫描抽象出一个BeanFactoryPostProcessor:

public class ComponentScanPostProcessor implements BeanFactoryPostProcessor {
    // postProcessBeanFactory在context.refresh()时调用
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        try {
            //查找类上有没有加@ComponentScan注解
            ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
            if(componentScan != null){
                //获取注解上的属性(包路径)
                for (String p : componentScan.basePackages()) {
//                System.out.println(p);  // com.cherry.a05.component
                    // 修改包名转为路径 --> 子包下的所有的类
                    String packagePath = "classpath*:"+p.replace(".","/")+"/**/*.class";
                    // System.out.println(packagePath);
                    CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
                    Resource[] resources = new PathMatchingResourcePatternResolver().getResources(packagePath);
                    for(Resource res:resources){
                        // System.out.println(res);
                        MetadataReader reader = factory.getMetadataReader(res);
                        System.out.println(reader.getClassMetadata().getClassName());
                        // 判断是否加入了@Component
                        System.out.println("是否加了@Component: "+reader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));
                        System.out.println("是否加了@Component及其派生注解: "+reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));

                        if(reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()) ||
                                reader.getAnnotationMetadata().hasAnnotation(Component.class.getName())){
                            // 创建一个BeanDefinition
                            AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();
                            // 为BeanDefinition生成Bean Name
                            AnnotationBeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
                            // 判断 configurableListableBeanFactory 是否为 DefaultListableBeanFactory 的实现
                            if (configurableListableBeanFactory instanceof DefaultListableBeanFactory beanFactory) {
                                String beanName = beanNameGenerator.generateBeanName(bd, beanFactory);
                                // 将BeanDefinition加入到BeanFactory中
                                beanFactory.registerBeanDefinition(beanName, bd);
                            }
                        }
                    }
                }
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

在主方法直接将bean工厂后处理器注册到bean工厂中即可:

context.registerBean(ComponentScanPostProcessor.class);

5.2 对@Bean注解的解析

将@Bean标注的方法变成BeanDefinition并加入到容器中。

@SpringBootApplication
public class A06ApplicationTest {
    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("config",Config.class);
        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        // 读取Config类的信息
        MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/cherry/a05/Config.class"));
        // 拿到所有被@Bean注解标记的方法
        Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
        for(MethodMetadata metadata:methods){
            System.out.println(metadata.toString());
            // 将方法信息生成对应的BeanDefinition
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
            builder.setFactoryMethodOnBean(metadata.getMethodName(), "config");
            builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
            AbstractBeanDefinition bd = builder.getBeanDefinition();
            // 加入到BeanFactory中
            context.getDefaultListableBeanFactory().registerBeanDefinition(metadata.getMethodName(),bd);
        }

        context.refresh();
        System.out.println("===========");
        for(String name:context.getBeanDefinitionNames()){
            System.out.println(name);
        }
    }
}

5.3 对@Mapper注解的解析

public class MapperPostProcessor implements BeanDefinitionRegistryPostProcessor {
    
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) {
        // 扫描Mapper包下的资源
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            Resource[] resources = resolver.getResources("classpath:com/cherry/a05/mapper/**/*.class");
            CachingMetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory();
            for(Resource res:resources){
                MetadataReader reader = metadataReaderFactory.getMetadataReader(res);
                ClassMetadata classMetadata = reader.getClassMetadata();
                // 判断是否为接口
                if (classMetadata.isInterface()) {
                    // 生成对应的 BeanDefinition
                    AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class).
                            addConstructorArgValue(classMetadata.getClassName())
                            .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)//设置自动装配
                            .getBeanDefinition();
                    AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
                    String beanName = generator.generateBeanName(bd, beanFactory);
                    beanFactory.registerBeanDefinition(beanName, bd);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinitionRegistryPostProcessor.super.postProcessBeanFactory(beanFactory);
    }
}

标签:生命周期,System,class,Bean,处理器,context,println,public,out
From: https://www.cnblogs.com/lilyflower/p/18240615

相关文章

  • Spring常用注解,自动扫描装配Bean
    1引入context命名空间(在Spring的配置文件中),配置文件如下:Xml代码xmlns:context="http://www.springframework.org/schema/context"http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd......
  • 【JavaScript】了解 Sass:现代 CSS 的强大预处理器
    我已经从你的全世界路过像一颗流星划过命运的天空很多话忍住了不能说出口珍藏在我的心中只留下一些回忆                     ......
  • 软件测试————Bug的定义及生命周期
    目录一、Bug的定义二、Bug的生命周期   三、Bug的等级划分一、Bug的定义    定义:⼀个计算机bug指在计算机程序中存在的⼀个错误(error)、缺陷(flaw)、疏忽(mistake)或者故障(fault),这些bug使程序⽆法正确的运⾏。二、Bug的生命周期    1、New(新......
  • 微信小程序加载、更新和生命周期、分享、转发、获取头像、获取昵称、手机号、客服功能
    【上拉下拉加载】1后端和路飞项目的课程表相对应234-----wxml-------567<viewwx:for="{{goods}}"wx:key="index">{{item.name}}</view>8910------js-----------111213Page({14data:{15page:1,16goods:[]......
  • Intellij插件之调试停止生命周期
    Intellij插件之调试停止生命周期目录Intellij插件之调试停止生命周期调试会话的创建调试停止调试会话各个监听器停止顺序调试会话的创建调试会话的创建由XDebuggerManager.startSessionAndShowTab接口创建,返回一个类型为XDebugSession的实例。它会在Debug窗口创建一个......
  • 1_关于BeanFactory与ApplicationContext的联系和区别
    BeanFactory与ApplicationContext1.容器和接口1.1BeanFactory与ApplicationContext的联系与区别:ConfigurableApplicationContext是ApplicationContext的子接口,而ApplicationContext接口又是BeanFactory的子接口。因此ConfigurableApplicationContext接口简介继承了Bean......
  • Windows系统如何实现对高通ARM处理器的支持探讨
    近年来,随着移动设备和低功耗计算的兴起,ARM架构的处理器越来越受到关注。微软作为操作系统领域的巨头,推出了Windows系统对高通公司开发的ARM架构处理器的支持,这无疑引起了广泛的兴趣与讨论。那么,微软是如何实现对ARM处理器的支持的呢?是否采用了原生支持?是否由于增加了抽象层......
  • Vue父子组件生命周期执行顺序
    顺序执行顺序:父组件先创建,然后子组件创建;子组件先挂载,然后父组件挂载,即“父beforeCreate->父create->子beforeCreate->子created->子mounted->父mounted”。在单一组件中,钩子的执行顺序是beforeCreate->created->mounted->…->destroyed,但当父子组件嵌套时,父组件和......
  • Java动态获取实现类 Class.forName(clazz).newInstance()和applicationContext.getBea
    Java动态获取实现类Class.forName(clazz).newInstance()和applicationContext.getBean,beanMap寻找方式,JavaMap定义和初始化方法1.定义枚举类MyServiceTypeEnum.javapackagecom.example.core.mydemo.bean;publicenumMyServiceTypeEnum{SUBMIT_ORDER_SUCCESS("s......
  • rabbitMq实现系统内的短信发送设计&动态获取BEAN
    rabbitMq实现系统内的短信发送设计&动态获取BEAN1.短信非系统的重要节点操作,可以在任务完成之后,比如下单成功,发送下单成功的mq消息,短信服务接收到mq消息,动态的判断该短信的code,通过全局公共的父类(调用中台等接口获取全部所有需要的对象参数),获取短信中的{mobile}等参数来替换短......