精华内容
下载资源
问答
  • Spring注解 生命周期初始化和销毁调用时机自定义初始化和销毁的方式@Bean指定初始化和销毁方法initializingBean和DisposableBean接口@PostConstruct 和@PreDestroyBeanPostProcessor 后置处理器BeanPostProcessor...

    Spring注解 生命周期

    初始化和销毁调用时机

    自定义初始化和销毁的方式

    @Bean指定初始化和销毁方法

    initializingBean和DisposableBean接口

    @PostConstruct 和@PreDestroy

    BeanPostProcessor 后置处理器

    BeanPostProcessor原理

    Spring底层对BeanPostProcessor的使用

    bean的生命周期:bean创建–>初始化–>销毁的过程

    在Spring中由容器管理bean的生命周期,我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期的是或来调用我们自己定义的初始化和销毁方法

    初始化和销毁调用时机

    生命周期:

    构造(对象创建)

    单实例:在容器启动的时候创建

    多实例:在每次获取的时候创建

    BeanPostProcessor.postProcessBeforeInitialization

    初始化

    对象创建完成并赋值好,调用初始化方法

    BeanPostProcessor.postProcessAfterInitialization

    销毁

    单实例:容器关闭的时候

    多实例:容器不会管理这个bean,容器不会调用销毁方法

    f286616a58e5a067582045c316b58bb0.png

    自定义初始化和销毁方法的方式:

    @Bean指定初始化和销毁方法

    实现initializingBean和DisposableBean接口

    @PostConstruct 和@PreDestroy

    BeanPostProcessor 后置处理器

    在初始化前后

    自定义初始化和销毁的方式

    @Bean指定初始化和销毁方法

    第一种方式是通过@Bean指定初始化和销毁方法

    @Bean(initMethod = "init",destroyMethod = "destroy")

    @Bean 有两个属性:

    initMethod = “init” 指定初始化方法名为init(在要创建的类中的方法)

    destroyMethod = “destroy” 指定销毁方法名为destroy

    这两个属性就等价于xml里Bean标签的init-method属性和destroy-method属性

    fd8949872c46bab7812df34f413f387d.png

    349a4990793984d07277a3b95bd0abe9.png

    单实例情况的输出:

    f1aebebb2319591adf9bb1a52884158c.png

    initializingBean和DisposableBean接口

    我们可以通过让Bean实现initializingBean接口定义初始化,的afterPropertiesSet()方法会在bean创建完成并属性赋值好后调用

    让Bean实现DisposableBean接口定义销毁,DisposableBean接口的destroy()方法会在容器关闭的时候调用

    109e5dbd0e1e9dc3fd92f3b066702bb9.png

    @PostConstruct 和@PreDestroy

    JSR250规范定义了两个注解:

    这两个注解都是标在方法上的

    @PostConstruct 在bean创建完成并且属性赋值完成,来执行初始化方法

    @PreDestroy 在容器销毁bean之前 会调用这个注解标注的方法

    cf031e6f75be385fd680aac74e9bd5d2.png

    BeanPostProcessor 后置处理器

    在bean初始化前后进行一些处理工作

    postProcessBeforeInitialization在bean创建后但初始化之前(例如initializingBean的afterPropertiesSet方法调用、initMethod指定的方法调用)

    postProcessAfterInitialization bean初始化之后调用

    这两个方法的参数:

    bean就是容器中已经创建的对象(返回也返回这个对象)

    beanName就是对象的名字

    26182f2ca86a2dffa0f1639c9577cd5b.png

    BeanPostProcessor原理

    populateBean()//1. 给属性赋值

    {

    //2. 后置处理器 调用PostProcessorsBeforeInitialization()方法

    applyBeanPostProcessorsBeforeInitialization

    //3. 调用自定义初始化方法

    invokeInitMethods

    //4. 后置处理器 调用PostProcessorsAfterInitialization()方法

    applyBeanPostProcessorsAfterInitialization

    }

    在doCreateBean方法中

    我们可以看到是先调populateBean()方法对bean的属性进行赋值,然后再调用initializeBean()方法

    62819df23f3286733d21a1d70a6a8aeb.png

    initializeBean()方法中

    1d652a95146a5427c588b0a693b7c79c.png

    applyBeanPostProcessorsBeforeInitialization()方法

    这个方法就是把所有的后置处理器都拿出来,然后调用每个的postProcessBeforeInitialization方法,如果有一个为null,就返回(后面的后置处理器就不调用了)

    44c37ab478ae59ce720274e6bd7dc378.png

    Spring底层对BeanPostProcessor的使用

    展开全文
  • 1 自定义注解 Annotation ...import java.lang.annotation.*; @Target({ElementType.TYPE, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface WeaponAlgorithm {

    0 直接看实现

    1 自定义注解 Annotation

    这里给出自定义注解的例子:

    package com.soul.weapon.algorithm.annotation;
    
    import java.lang.annotation.*;
    
    @Target({ElementType.TYPE, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface WeaponAlgorithm {
        String algoName () default "";
    }
    

    注意注解的申明是用@interface来声明的:
    然后这里对每一个参数做简单说明:

    • @Target 说明注解的使用范围
      • TYPE: 用于描述类、接口(包括注解类型) 或enum声明
      • FILED: 用于描述域
    • @Retention 说明注解可以被保留到什么地方
      • 1 RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
      • 2 RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
      • 3 RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;

    这3个生命周期分别对应于:Java源文件(.java文件) —> .class文件 —> 内存中的字节码。
    明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解,比如接下来要讲到的在运行过程过获得某种注解的所有的类;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife 和 mapstruct 等),就用 CLASS注解;如果只是做一些检查性的操作,比如** @Override**和 @SuppressWarnings,则可选用 SOURCE 注解。

    • @Documentation: 用于生成javadoc
    • @Inherited: 说明被改注解注释的子类会继承该注解

    2 简单工厂模式 简单甚至不简单的工厂Ref

    简单说明一下,比如你有一个业务要求是,实现n种车的drive方法,那最普通的就如下:
    分别实现其类然后调用,这未免有点难看:

    public class Driver1 {
    
      public static void main(String[] args) {
        Car1 car = new Car1();
        Car2 car = new Car2();
        Car3 car = new Car3();
        Car4 car = new Car4();
      }
    
    }
    

    使用简单工厂模式就是说,来一个carFactory类,我所有车的实例的创建和使用都通过carFactory,然后传具体的参数就能实例化相应的类:

    public class Driver2 {
      public Car car;
      public static void createCar(String name) {
        switch (name) {
        case "car1":
          car = new Car3();
          break;
        case "car2":
          car = new Car3();
          break;
        case "car3":
          car = new Car3();
          break;
        default:
          car = null;
          break;
        }
        LOG.info("Created car name is {}", name);
      }
      public drive() { car.drive();}
    }
    

    但是这里有一个问题,没有遵循开闭原则(开放扩展,关闭修改的原则),那么造成没有遵循的原因是什么?因为每一个实现的类的名称是我们手动写到代码里的,当这些相关的类的名称是我们通过代码可以获取的时候,我们就可以解决该问题了,于是我们使用注解

    3 使用注解的反射来完善包含简单工厂模式的策略模式

    • 策略模式 将具体的算法封装到一个context类,context可以根据传入的参数自动调取相关的算法,简单工厂模式还是与之很像的
    • 解决了什么问题
      策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完全的都是相同的工作,只是实现不同,用户通过context以相同的方式调用所有的算法,减少了各种算法实现类与使用类之间的耦合
    • 和工厂模式的区别
      • 1 工厂模式,主要是将对象的创建,和使用进行解耦,而策略模式,主要将策略的定义创建,和使用进行解耦,主要是他们针对的对象不同,一个主体是实体类,另一个是策略类,我个人感觉核心思想都是一样的

    3.1 示例分析:

    接着上面#1的注解,一个策略模式的例子如下(个人理解,欢迎交流)

    • 1 定义一个接口,这样所有的算法类的调用都按照这个接口调用即可:
    public interface Algorithm {
        /**
         *
         * 使用指定的工厂里的函数来处理input
         * @param input
         * @return
         */
        String exAlgo(String input);
    }
    
    • 2 为这个接口实现一个算法:
    @WeaponAlgorithm(algoName = "airMissilePipeTest")
    public class AirMissilePipeTest implements Algorithm {
    
        @Override
        public String exAlgo(String input) {
            Logger LOG = LoggerFactory.getLogger(AirMissilePipeTest.class);
            LOG.info("airMissilePipeTest algo executing!");
            return input;
        }
    }
    
    • 3 从用户层面考虑,为用户实现一个上下文类,这个上下文类帮助用户实例化对应的算法类,然后调用相关的算法类:
    public class AlgoFactoryContext {
        private static final Logger LOG = LoggerFactory.getLogger(AlgoFactoryContext.class);
        private static Map<String, Class> allStrategies;
    
        static {
            Reflections reflections = new Reflections("com.soul.weapon.algorithm.impl",
                    new SubTypesScanner(),
                    new TypeAnnotationsScanner(),
                    new FieldAnnotationsScanner());
            Set<Class<?>> annotatedClasses =
                    reflections.getTypesAnnotatedWith(WeaponAlgorithm.class);
            allStrategies = new ConcurrentHashMap<String, Class>();
            for (Class<?> classObject : annotatedClasses) {
                WeaponAlgorithm annotatedAlgo = (WeaponAlgorithm) classObject
                        .getAnnotation(WeaponAlgorithm.class);
                allStrategies.put(annotatedAlgo.algoName(), classObject);
            }
            allStrategies = Collections.unmodifiableMap(allStrategies);
        }
    
        private Algorithm algoExecutor;
    
        public AlgoFactoryContext (String requiredAlgoName){
            if(allStrategies.containsKey(requiredAlgoName)) {
                LOG.info("algo name is {}", requiredAlgoName);
                try {
                    algoExecutor =  (Algorithm) allStrategies.get(requiredAlgoName).getDeclaredConstructor().newInstance();
                } catch (NoSuchMethodException | InstantiationException
                        | InvocationTargetException | IllegalAccessException ex) {
                    LOG.error("Instantiate algo Failed: ", ex);
                }
            } else {
                LOG.error("algo with name: {} not exist!", requiredAlgoName);
            }
        }
    
        public void execAlgo(String dataString) {
            algoExecutor.exAlgo(dataString);
        }
    }
    
    
    
    • 4 调用示例:
            AlgoFactoryContext ctx = new AlgoFactoryContext("airMissilePipeTest");
            ctx.execAlgo("info to process!");
    

    4 当使用spritboot的自动装配来简化以免手动写reflections

    • 1 定义一个接口,这样所有的算法类的调用都按照这个接口调用即可:
    public interface Algorithm {
        /**
         *
         * 使用指定的工厂里的函数来处理input
         * @param input
         * @return
         */
        String exAlgo(String input);
    }
    
    • 2 为这个接口实现一个算法:
    @Service(value = "airMissilePipeTest")
    public class AirMissilePipeTest implements Algorithm {
    
        @Override
        public String exAlgo(String input) {
            Logger LOG = LoggerFactory.getLogger(AirMissilePipeTest.class);
            LOG.info("airMissilePipeTest algo executing!");
            return input;
        }
    }
    
    • 3 创建上下文类然后自动注入实现接口的那些类:
    @Service
    public class AlgoFactoryContext {
        private static final Logger LOG = LoggerFactory.getLogger(AlgoFactoryContext.class);
    
        @Autowired(required = true)
        private Map<String, Algorithm> allStrategies;
    
        private Algorithm algoExecutor;
    
        public void execAlgo(String requiredAlgoName, String dataString) {
            if(allStrategies.containsKey(requiredAlgoName)) {
                LOG.info("algo name is {}", requiredAlgoName);
                algoExecutor =  (Algorithm) allStrategies.get(requiredAlgoName);
            } else {
                LOG.error("algo with name: {} not exist!", requiredAlgoName);
            }
            algoExecutor.exAlgo(dataString);
        }
    }
    
    • 4 调用:这里需要注意,如果是单独new一个AlgoFactoryContext,并没有办法完成自动装配,猜测原因是,由于使用了sprintboot的autoWire,那么所有依赖都要保证有@component和@sevice/@resouce等去注解,这些注解保证了sprinboot会将这些依赖给管理起来,所以如果new,那么autoWire无法发挥作用
    @Slf4j
    @RestController
    @RequestMapping("/free/test")
    @RequiredArgsConstructor
    public class FreePipeTestController {
    
        @Autowired
        private AlgoFactoryContext ctx; // by autowire, so ctx will scan and get all 
        // implement of the algorithm interface
    
        private final PipeTestService pipeTestService;
    
        @Api
        @GetMapping(value = "/{id}")
        public PipeTest getById(@PathVariable("id") String id)
        {
            // add test for the algo factory:
            ctx.execAlgo("airMissilePipeTest", "telegram from socket!");
            return pipeTestService.getById(id);
        }
    ...
    }
    
    展开全文
  • Java注解学习笔记

    2021-03-13 22:44:58
    前言一直都在使用注解,但是一直都没有用的很明白,后来被逼的发现不搞明白真的就...注解说明Java注解又称Java标注,是Java语言5.0版本开始支持加入源代码的特殊语法元数据。为我们在代码中添加信息提供了一种形式...

    前言

    一直都在使用注解,但是一直都没有用的很明白,后来被逼的发现不搞明白真的就没有办法愉快的写代码了,所以,这篇《Java中的注解学习笔记》就呼之欲出了,在我的各种不情愿之下,在我浪费了好几个小时的情况下,总算对这个注解有了一个入门的学习,对付一般的注解问题是足够了。

    注解说明

    Java注解又称Java标注,是Java语言5.0版本开始支持加入源代码的特殊语法元数据。为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据。Java语言中的类、方法、变量、参数和包等都可以被标注。和Javadoc不同,Java标注可以通过反射获取注解内容。在编译器生成类文件时,注解可以被嵌入到字节码中。Java虚拟机可以保留注解内容,在运行时可以获取到注解内容。

    内置注解

    Java定义了一套注解,共有7个,3个在java.lang中,剩下4个在java.lang.annotation中。

    作用在代码的注解是:

    @Override – 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。

    @Deprecated – 标记过时方法。如果使用该方法,会报编译警告。

    @SuppressWarnings – 指示编译器去忽略注解中声明的警告。

    作用在其他注解的注解(或者说元注解)是:

    @Retention – 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。

    @Documented – 标记这些注解是否包含在用户文档中。

    @Target – 标记这个注解应该是哪种Java成员。

    @Inherited – 标记这个注解是继承于哪个注解类(默认注解并没有继承于任何子类)

    从Java 7开始,额外添加了3个注解:

    @SafeVarargs – Java 7开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。

    @FunctionalInterface – Java 8开始支持,标识一个匿名函数或函数式接口。

    @Repeatable – Java 8开始支持,标识某注解可以在同一个声明上使用多次。

    元注解

    元注解就是上面说到的作用在其他注解上的注解。

    @Retention:表明该注解的生命周期

    生命周期类型

    描述

    RetentionPolicy.SOURCE

    标记的注释仅保留在源级别中,并由编译器忽略。

    RetentionPolicy.CLASS

    标记的注释在编译时由编译器保留,但Java虚拟机(JVM)会忽略。

    RetentionPolicy.RUNTIME

    标记的注释由JVM保留,因此运行时环境可以使用它。

    @Documented:表明该注解标记的元素可以被Javadoc或类似的工具文档化

    @Target: 表明该注解可以应用的java元素类型

    Target类型

    描述

    ElementType.TYPE

    可以应用于类的任何元素。

    ElementType.FIELD

    可以应用于字段或属性。

    ElementType.METHOD

    可以应用于方法级注释。

    ElementType.PARAMETER

    可以应用于方法的参数。

    ElementType.CONSTRUCTOR

    可以应用于构造函数。

    ElementType.LOCAL_VARIABLE

    可以应用于局部变量。

    ElementType.ANNOTATION_TYPE

    可以应用于注释类型。

    ElementType.PACKAGE

    可以应用于包声明。

    ElementType.TYPE_PARAMETER

    1.8版本新增,应用于类型变量

    ElementType.TYPE_USE

    1.8版本新增,应用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型)

    @Inherited:表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解

    @Repeatable:Java SE 8中引入的,@Repeatable注释表明标记的注释可以多次应用于相同的声明或类型使用(即可以重复在同一个类、方法、属性等上使用)。

    自定义注解

    其实说了这么多,都是一些总结性的知识点,我敢说到现在,大家还是对注解是云里雾里的。想要更好的认识注解,只有我们自己定义一个注解,来实现一个我们的注解,通过实现一个我们自己的注解来熟悉注解的工作流程。

    Java中自定义注解和创建一个接口相似,声明一个注解要用到以下东西:

    修饰符:访问修饰符必须为public,不写默认为pubic;

    关键字:关键字为@interface;

    注解名称:注解名称为自定义注解的名称,使用时还会用到;

    注解类型元素:注解类型元素是注解中内容,可以理解成自定义接口的实现部分。

    同时需要注意以下事项:

    注解方法不能有参数;

    注解方法的返回类型局限于原始类型,字符串,枚举,注解,或以上类型构成的数组;

    注解方法可以包含默认值;

    注解可以包含与其绑定的元注解,元注解为注解提供信息。

    规则知道了,下面我来编码实现一个自定义的注解。比如我们在实现一个自定义的ORM框架的时候,都会通过注解来实现数据表名与JAVA类的映射,表字段与JAVA类字段的映射关系,下面就来简单实现这个功能。

    定义Table注解:

    package com.jellythink.annotation;

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

    @Target(value={ElementType.TYPE})

    @Retention(RetentionPolicy.RUNTIME)

    public @interface Table {

    String value();

    }

    定义字段注解:

    package com.jellythink.annotation;

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

    @Target(value={ElementType.FIELD})

    @Retention(RetentionPolicy.RUNTIME)

    public @interface FieldMapping {

    String name();

    String type();

    int length();

    }

    应用注解:

    package com.jellythink;

    import com.jellythink.annotation.FieldMapping;

    import com.jellythink.annotation.Table;

    @Table("tb_student")

    public class Student {

    @FieldMapping(name = "id", type = "int", length = 10)

    private int id;

    @FieldMapping(name = "name", type = "varchar", length = 6)

    private String stuName;

    @FieldMapping(name = "age", type="int", length = 4)

    private String stuAge;

    // 省略getter and setter

    }

    读取注解信息:

    package com.jellythink;

    import com.jellythink.annotation.Table;

    import com.jellythink.annotation.FieldMapping;

    import java.lang.reflect.Field;

    public class Main {

    public static void main(String[] args) {

    try {

    Class clazz = Class.forName("com.jellythink.Student");

    // 查询类上的注解

    Table tbStudent = (Table)clazz.getAnnotation(Table.class);

    System.out.println(tbStudent.value());

    // 查询属性上的注解

    Field stuId = clazz.getDeclaredField("id");

    FieldMapping fieldStuId = stuId.getAnnotation(FieldMapping.class);

    System.out.println(fieldStuId.name() + "--" + fieldStuId.type() + "--" + fieldStuId.length());

    Field stuName = clazz.getDeclaredField("stuName");

    FieldMapping fieldStuName =

    stuName.getAnnotation(FieldMapping.class);

    System.out.println(fieldStuName.name() + "--" + fieldStuName.type() + "--" + fieldStuName.length());

    Field stuAge = clazz.getDeclaredField("stuAge");

    FieldMapping fieldStuAge =

    stuName.getAnnotation(FieldMapping.class);

    System.out.println(fieldStuAge.name() + "--" + fieldStuAge.type() + "--" + fieldStuAge.length());

    // 通过上面查询到的数据拼接成SQL语句

    String name = "果冻";

    String sql =

    "select * from " + tbStudent.value() + " where " + fieldStuName.name() + " = '" + name + "'";

    System.out.println("SQL=" + sql);

    } catch (Exception e) {

    // Handle the exception

    }

    }

    }

    通过上面的代码,有木有感受到自定义注解还是非常简单的;同时有没有感觉到注解这个功能是非常强大的。

    总结

    总的来说,注解这个功能很强大,但是使用起来确是非常简单的,这就是牛叉东西的特点,好用又让人不感觉到复杂。以后再遇到注解东西,内心就不再犯怵,不再迷茫了。

    果冻想,认真玩技术的地方。

    2020年10月20日,于内蒙古呼和浩特。

    展开全文
  • 生命周期initMethod和destroyMethodBean定义public class Car {public Car() {System.out.println("car constructor");}public void init(){System.out.println("car init");}public void destroy(){System.out....

    生命周期

    initMethod和destroyMethod

    Bean定义

    public class Car {

    public Car() {

    System.out.println("car constructor");

    }

    public void init(){

    System.out.println("car init");

    }

    public void destroy(){

    System.out.println("car destroy");

    }

    }

    配置类

    bean创建--初始化--销毁

    可以自定义初始化和销毁方法

    初始化:对象创建完成,并赋值完成,调用初始化方法

    销毁: 容器关闭进行销毁(单实例)

    ​ 多实例容器不会管理这个bean

    @Configuration

    public class MyCOnfigOfLifeCycle {

    @Bean(initMethod = "init",destroyMethod = "destroy")

    public Car car(){

    return new Car();

    }

    }

    获取容器

    @Test

    public void test01(){

    printBeans(applicationContext);

    // 关闭容器

    applicationContext.close();

    }

    private void printBeans(AnnotationConfigApplicationContext applicationContext){

    String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();

    for (String beanDefinitionName : beanDefinitionNames) {

    System.out.println(beanDefinitionName);

    }

    }

    InitializingBean和DisposableBean

    Bean定义

    public class Cat implements InitializingBean, DisposableBean {

    @Override

    public void destroy() throws Exception {

    System.out.println("cat destroy");

    }

    @Override

    public void afterPropertiesSet() throws Exception {

    System.out.println("cat initialize");

    }

    }

    实现了InitializingBean和Disposable后,也可以实现初始化和销毁的方法

    PostConstruct和PreDestroy

    Bean定义

    public class Dog {

    public Dog(){

    System.out.println("dog constructor");

    }

    @PostConstruct

    public void init(){

    System.out.println("dog init");

    }

    @PreDestroy

    public void destroy(){

    System.out.println("dog destroy");

    }

    }

    BeanPostProcessor

    bean

    定义

    public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

    System.out.println("before init" + beanName);

    return bean;

    }

    @Override

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

    System.out.println("after init" + beanName);

    return bean;

    }

    }

    加入到bean中,可以发现每个bean初始化前后都会执行功能

    postProcessBeforeInitialization将在一个bean被完全初始化前进行回调,此时对应的bean已经实例化了,但是对应的属性注入等还没有进行,即在调用InitializingBean的afterPropertiesSet()方法或bean对应的init-method之前

    postProcessAfterInitialization将在bean被完全初始化后进行回调,此时对应的依赖注入已经完成,即在调用InitializingBean的afterPropertiesSet()方法或对应init-method方法之后。

    postProcessBeforeInitialization方法的返回值会被Spring容器作为处理后的Bean注册到容器中。如果你在postProcessBeforeInitialization方法中重新构造了一个Bean进行返回,而不是返回参数中的bean;那么你返回的Bean将会被注册到Spring容器中。而原来在Spring中配置的Bean(被Spring实例化的Bean)将会被覆盖。

    一旦这两个方法返回null,就不会执行后面的postProcessBefore/AfterInitialization,(在applyBeanPostProcessorsBeforeInitialization中)

    for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {

    BeanPostProcessor processor = (BeanPostProcessor)var4.next();

    current = processor.postProcessBeforeInitialization(result, beanName);

    if (current == null) {

    return result;

    }

    }

    步骤:

    populateBean给Bean赋值

    initializeBean{ applyBeanPostProcessorsBeforeInitialization,

    ​ invokeInitMethods, // 自定义初始化

    ​ applyBeanPostProcessorsAfterInitialization}

    底层使用

    bean赋值,bean注入,@autowire,生命周期注解功能,@Async

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    展开全文
  • JAVA注解相关知识总结

    2021-03-13 22:44:23
    注解的概念java注解:比较官方的说法:从JDK5开始,Java增加对元数据的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的...
  • 类的生命周期java类的生命周期就是指一个class文件从加载到卸载的全过程。完整的生命周期会经历加载、连接、初始化、使用、和卸载五个阶段,当然也有在加载或者连接之后没有被初始化就直接被使用的情况,如图所示:...
  • Java WebSocket生命周期

    2021-02-28 11:13:48
    我们将仔细探讨其生命周期的顺序和语义,以及Java WebSocket API如何提供API和注解来支持处理这些事件。一、WebSocket协议与基于HTTP的技术不同,WebSocket具有生命周期。此生命周期周期由WebSocket协议支撑。W...
  • 一个线程由创建到死亡会经历自己的生命周期,我们可能会经常在博客中看到线程的“Running”状态,但是通过阅读Thread类的源码你又找不到“Running”状态,那么Java线程中到底有没有Running状态?首先通过查看...
  • 第十一章 对象的生命周期11.1 创建对象的方式在Java程序中,对象可以被显式或隐式地创建,创建一个对象就是指构造一个类的实例。前提条件是这个类已经被初始化。有4种创建对象的方法:用new语句创建对象,这是最常见...
  • Java1.5推出元注解后,时下最活跃的开源社区Spring便开始大力推崇,原本...在自定义元注解@Annotation的时候,有两个特性是必须要定义清楚的,一个是Target(注解目标),另一个就是Retention(注解生命周期,也叫声明...
  • 官方定义:Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。这个中间层就是对请求进行分发和控制。 ...
  • java – JUnit生命周期

    2021-03-08 16:43:51
    我有一个生命周期问题,用JUnit做一些测试套件.为了编写方便的JPA 2.0单元测试作为Java开发人员我想要:>在所有测试套件之前初始化一次EntityManagerFactory实例.我通过使用@BeforeClass注释来实现该对象>实例...
  • JVM详解之对象生命周期什么叫垃圾?垃圾是怎样产生的?垃圾怎么回收?java和C、C++中的垃圾区别C和C++中的对象生存周期完全有编程者决定,而java中对象的生存周期默认由虚拟机决定,但是也允许编程者显式的调用gc()...
  • Java 对象生命周期在JVM运行空间中,对象的整个生命周期大致可以分为7个阶段:创建阶段(Creation)、应用阶段(Using)、不可视阶段(Invisible)、不可到达阶段(Unreachable)、可收集阶段(Collected)、终结阶段...
  • Java Filter过滤器+Listen监听器啥是过滤器顾名思义即过滤掉一些东西,比如我们经历的高考中考都是过滤器,他过滤掉一些在学习这一方面不是很好的人,而那些成绩好的人则升入高中,大学。但是java中的过滤器与生活中...
  • 一、Bean的生命周期流程Bean创建 —— 初始化 —— 销毁创建:单实例:在容器启动时创建对象多实例:每次调用时创建对象初始化:都是在对象创建完成后,调用初始化方法销毁:单实例:容器关闭时,调用销毁方法多实例...
  • bean的定义形成应用程序的骨干是由Spring IoC容器所管理...bean定义包含所需要的容器要知道以下称为配置元数据的信息:如何创建一个beanBean 生命周期的详细信息Bean 依赖关系上述所有配置元数据转换成一组的下列属...
  • 本文主要想讨论是对象和bean,对象和bean的关系,对象和bean初始化过程(或者说生命周期有何异同),spring 对托管的对象究竟做了些什么工作
  • Java面试题1-Java基础

    2021-02-27 14:52:22
    表示这是一个ASCII字符(00~7F) 如果一个字节,以11开头,连续的1的个数暗示这个字符的字节数 一个utf8数字占1个字节 一个utf8英文字母占1个字节 少数是汉字每个占用3个字节,多数占用4个字节 说说你对Java注解的...
  • 理解对象和Bean的关系java 是一种面向对象的语言,简而言之,一切皆对象。Bean天然也是对象,只不过它是托管给 Bean 工厂管理着的对象。javajava 对象如何被建立在写代码时,咱们一般用下面的语句来建立一个对象:...
  • 简介大家都知道线程是有生命周期,但是彤哥可以认真负责地告诉你网上几乎没有一篇文章讲得是完全正确的。常见的错误有:就绪状态、运行中状态(RUNNING)、死亡状态、中断状态、只有阻塞没有等待状态、流程图乱画等,...
  • java注解

    2021-02-27 16:31:23
    注解:元注解的作用就是负责注解...Java5.0定义的元注解:1.@Target,2.@Retention,3.@Documented,4.@Inherited这些类型和它们所支持的类在java.lang.annotation包中可以找到。下面我们看一下每个元注解的作用和...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 112,099
精华内容 44,839
关键字:

java注解生命周期

java 订阅