对象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>
运行结果如图所示:
-
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>
运行结果如图所示:
-
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>
-
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提供的。
注册过程
当创建Person对象时,扫描到Person对象中存在@PostConstruct & @PreDestroy注解时,会调用CommonAnnotationBeanPostProcessor 处理器,解析注册 @PostConstruct & @PreDestroy,如图:
注册完成后如图
执行过程
@Autowired, @Value @Inject 解析过程
@Autowired, @Value 注解是在AutowiredAnnotationBeanPostProcessor.java 中完成注册的,具体过程如图。