Loading

对象Constructor构造函数和@PostConstruct&@PreDestroy解析详解

构造函数解析

实例化之前,如何选择构造函数。

构造函数解析示例,code 如下。

定义实体类:

package com.gientech.constructor;

public class Person {

    private String name;

    private int id;

    private int age;

    private String sex;


    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }


    public Person(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

新增配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="person" class="com.gientech.constructor.Person">
        <property name="name" value="lisi"></property>
        <property name="sex" value="man"></property>
<!--        <constructor-arg name="sex" value="man"></constructor-arg>-->
<!--        <constructor-arg name="name" value="zhangsan"></constructor-arg>-->
    </bean>
</beans>

新增启动类

package com.gientech.constructor;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ConstructorTest {

    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("constructortest.xml");
        Person bean = ac.getBean(Person.class);
        System.out.println(bean.getName());
    }
}

构造函数解析执行顺序如下:
doCreateBean -> createBeanInstance -> autowireConstructor -> ConstructorResolver.autowireConstructor

determineCandidateConstructors 方法作用是获取构造器,有4种场景

  • 1 如果有多个Autowired,required为true,不管有没有默认构造方法,会报异常

package com.gientech.constructor;

import org.springframework.beans.factory.annotation.Autowired;

public class Person {

    private String name;

    private int id;

    private int age;

    private String sex;


    public Person() {
    }

    @Autowired
    public Person(String name) {
        this.name = name;
    }


    @Autowired
    public Person(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

<?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: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 https://www.springframework.org/schema/context/spring-context.xsd">


    <context:component-scan base-package="com.gientech"></context:component-scan>

    <bean id="person" class="com.gientech.constructor.Person">
        <constructor-arg name="sex" value="man"></constructor-arg>
        <constructor-arg name="name" value="zhangsan"></constructor-arg>
    </bean>
</beans>

运行结果如图所示:
场景1

  • 2 如果只有一个Autowired,required为false,没有默认构造方法,会报警告

package com.gientech.constructor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

public class Person {

    private String name;

    private int id;

    private int age;

    private String sex;


//    public Person() {
//    }

    @Autowired(required = false)
    public Person(String name) {
        this.name = name;
    }


//    @Autowired
    public Person(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

<?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: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 https://www.springframework.org/schema/context/spring-context.xsd">


    <context:component-scan base-package="com.gientech"></context:component-scan>

    <bean id="person" class="com.gientech.constructor.Person">
        <property name="name" value="lisi"></property>
        <property name="sex" value="man"></property>
    </bean>
</beans>

运行结果如图所示:
constructorwarn1

  • 3 如果没有Autowired注解,定义了两个及以上有参数的构造方法,没有无参构造方法,且不是通过xml配置文件进行加载,使用@Component进行加载就会报错

package com.gientech.constructor;

import org.springframework.stereotype.Component;

@Component
public class Person {

    private String name;

    private int id;

    private int age;

    private String sex;



    public Person(String name) {
        this.name = name;
    }


    public Person(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

<?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: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 https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.gientech"></context:component-scan>

</beans>

constructorerror2

  • 4 其他情况都可以,但是以有Autowired的构造方法优先,然后才是默认构造方法

@PostConstruct & @PreDestroy 解析过程

代码如下:

package com.gientech.constructor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class Person {

    private String name;

    private int id;

    private int age;

    private String sex;

    public Person(){
        System.out.println("无参构造方法。。。");
    }


    public Person(String name) {
        this.name = name;
    }


    public Person(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

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

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


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

注册过程

@PostConstruct & @PreDestroy注解也是jdk提供的。
注册过程
@PostConstruct & @PreDestroy解析过程

当创建Person对象时,扫描到Person对象中存在@PostConstruct & @PreDestroy注解时,会调用CommonAnnotationBeanPostProcessor 处理器,解析注册 @PostConstruct & @PreDestroy,如图:
解析@PostConstruct & @PreDestroy

注册完成后如图
@PostConstruct & @PreDestroy解析完成

执行过程

@Autowired, @Value @Inject 解析过程

@Autowired, @Value 注解是在AutowiredAnnotationBeanPostProcessor.java 中完成注册的,具体过程如图。

注册过程

autowired注册过程

posted @ 2024-03-22 09:02  zgcy123456  阅读(11)  评论(0编辑  收藏  举报