Spring中构造器、init-method、@PostConstruct、afterPropertiesSet孰先孰后,自动注入发生时间以及单例多例的区别

  

  首先明白,spring的IOC功能需要是利用反射原理,反射获取类的无参构造方法创建对象,如果一个类没有无参的构造方法spring是不会创建对象的。在这里需要提醒一下,如果我们在class中没有显示的声明构造方法,默认会生成一个无参构造方法,但是当我们显示的声明一个有参构造方法的时候,JVM不会帮我们生成无参构造方法,所以我们声明一个带参数的构造方法也需要声明一个无参构造方法。(题外话:如果父类声明一个有参构造方法,子类需要在构造方法第一行显示的调用父类构造方法,因为子类的对象也是父类的对象,所以在创建子类对象的同时也会创建父类的对象,如果父类有默认的无参构造函数,JVM会调用无参构造函数,但是有了有参的就需要我们在子类的构造函数中调用父类的有参构造函数)

1.Person类只有一个有参构造方法,报错如下:

No default constructor found; nested exception is java.lang.NoSuchMethodException: zd.dms.job.ebuy.Person.<init>()

2.大体知道有三种生命周期回调方法去参与到spring的生命周期,查阅了一下如下:(创建和销毁的执行顺序也是下面顺序)

  • 在指定方法上加上@PostConstruct 或@PreDestroy注解来制定该方法是在初始化之后还是销毁之前调用。
  • 通过实现 InitializingBean/DisposableBean 接口来定制初始化之后/销毁之前的操作方法;
  • 通过 <bean> 元素的 init-method/destroy-method属性指定初始化之后 /销毁之前调用的操作方法;

3.测试spring的顺序与注入的顺序与单例多例的问题

1.Person.java

package zd.dms.job.ebuy;

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

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

import zd.dms.dao.ebuy.GroupDao;

public class Person implements InitializingBean,DisposableBean{
    private String name;

    @Autowired
    private GroupDao groupDao;

    public Person() {
        System.out.println("---------------实例化一个Person对象----------");
        System.out.println("---------------groupDao is -----------"+groupDao);
    }

    public void init() {
        System.out.println("------------这是xml的init方法----------....");
        System.out.println("---------------groupDao is -----------"+groupDao);
    }

    public void destory() {
        System.out.println("---------------这是xml的destroy方法....");
        System.out.println("---------------groupDao is -----------"+groupDao);
    }

    @PostConstruct
    public void init2() {
        System.out.println("------------这是@PostConstruct的init方法----------....");
        System.out.println("---------------groupDao is -----------"+groupDao);
    }

    @PreDestroy
    public void destory2() {
        System.out.println("---------------这是@PreDestroy的destroy方法....");
        System.out.println("---------------groupDao is -----------"+groupDao);
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("-----------这是DisposableBean的destroy方法....");
        System.out.println("---------------groupDao is -----------"+groupDao);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("-------这是InitializingBean的afterPropertiesSet方法....");
        System.out.println("---------------groupDao is -----------"+groupDao);
    }
}

 -----------------------单例模式的xml配置以及结果---------------------------------------:

配置:

    <bean id="person" class="zd.dms.job.ebuy.Person" autowire="byType" destroy-method="destory" init-method="init"></bean> 

测试:将Person类注入到Action我们访问Action

@Namespace("/qlqTest")
@SuppressWarnings("all")
public class TestAction extends DMSActionSupport{

    /**
     *
     */
    private static final long serialVersionUID = -8934360924125349297L;

    @Autowired
    private GroupAndUserService groupAndUserService;
    @Autowired
    private Person person;

当我们第一次调用该实例方法的时候会创建对象,打印结果如下:

- ---------------实例化一个Person对象----------
---------------groupDao is -----------null
------------这是@PostConstruct的init方法----------....
---------------groupDao is -----------[email protected]
-------这是InitializingBean的afterPropertiesSet方法....
---------------groupDao is -----------[email protected]
------------这是xml的init方法----------....
---------------groupDao is [email protected]

证明对象创建的顺序:

    构造器-->自动注入-->@PostConstrut-->InitializingBean-->xml中配置init方法    

再次调用不会打印,证明默认是单例的  singleton,也就是无论我们访问多少次Action,Spring容器中只有一个这个对象。

销毁的时候的结果:

---------------这是@PreDestroy的destroy方法....
---------------groupDao is -----------[email protected]
-----------这是DisposableBean的destroy方法....
---------------groupDao is -----------[email protected]
---------------这是xml的destroy方法....
---------------groupDao is [email protected]

所以销毁顺序为:

  @PreDestroy--DisposableBean-->xml中destroy-method方法

 -----------------------多模式的xml配置以及结果---------------------------------------:

配置:

<bean id="person" class="zd.dms.job.ebuy.Person" autowire="byType" destroy-method="destory" init-method="init" scope="prototype"></bean>

我们多次访问Action,所以Action会多次调用Person对象,发现会多次创建Person对象,也就是请求一次会创建一个对象,也就是多例:

至于到底是该使用单例还是多例,这就需要我们平时的业务需求了,springMvc就是单例的,struts2默认就是多例的。我们也可以使用注解配置单例和多例,如下:

---------------------为了理解上面的单例多例的例子,继续测试---------------------

配置如下:

Action是struts默认多例:(注入Person类对象)

Person类模拟是service层,默认是单例(注入GroupDaoImpl对象)

GroupDaoImpl是多例

也就是我们上面的配置从Action到service到dao的作用域是多-单-多,我们多次访问Action,结果如下:

解释:

  我们每次访问action是多例所以每次会创建对象,而Person默认是单例,所以spring只会维护一个对象,即使GroupDaoImpl是多例模式,但是其已经注入到Person类中,而person不会创建新的对象,所以GroupDaoImpl也只会生成一个对象。只有在生成Person类的时候才会重新生成GroupDaoImpl且重新维护关系。所以上面在spring中出现对各TestAction,一个Person和一个GroupDaoImpl。

原文地址:https://www.cnblogs.com/qlqwjy/p/9417034.html

时间: 2024-10-04 03:30:28

Spring中构造器、init-method、@PostConstruct、afterPropertiesSet孰先孰后,自动注入发生时间以及单例多例的区别的相关文章

我被面试官给虐懵了,竟然是因为我不懂Spring中的@Configuration

现在大部分的Spring项目都采用了基于注解的配置,采用了@Configuration 替换标签的做法.一行简单的注解就可以解决很多事情.但是,其实每一个注解背后都有很多值得学习和思考的内容.这些思考的点也是很多大厂面试官喜欢问的内容. 在一次关于Spring注解的面试中,可能会经历面试官的一段夺命连环问: @Configuration有什么用?br/>@Configuration和XML有什么区别?哪种好?Spring是如何基于来获取Bean的定义的?@Autowired . @Inject.

Spring中的Autowired注解和Resource注解的区别

1.所属jar包不同,Autowired是Spring中的Resource是JSR-250规范定义的注解 2.自动装配时可以选择的参数不一样,具体的可以看其接口 Resource里面有这几个可以配置的,我只能看懂name 和 type,意思分别是按名称装配,按类型装配. 默认安装名称进行装配.当找不到与名称匹配的bean时才按照类型进行装配. 如果name属性一旦指定,就只会按照名称进行装配. 如果指定了type,则按照类型进行装配,找不到或者找到多个bean,都会抛出异常 autowired:

Spring第八章:Spring自动注入

一.自动注入 1.在 Spring 配置文件中对象名和 ref=”id”id 名相同使用自动注入,可以不配置<property/> 2.两种配置办法 2.1 在<bean>中通过 autowire=”” 配置,只对这个<bean>生效 2.2 在<beans>中通过 default-autowire=””配置,表当当前文件中所有<bean>都是全局配置内容 2.3 自动注入代码 2.3.1测试自动注入的实体类,老师和学生类 package com

Injection of autowired dependencies failed; autowire 自动注入失败,测试类已初始化过了Spring容器。

1 严重: StandardWrapper.Throwable 2 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'searchController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreatio

java代码中init method和destroy method的三种使用方式

在java的实际开发过程中,我们可能常常需要使用到init method和destroy method,比如初始化一个对象(bean)后立即初始化(加载)一些数据,在销毁一个对象之前进行垃圾回收等等. 周末对这两个方法进行了一点学习和整理,倒也不是专门为了这两个方法,而是在巩固spring相关知识的时候提到了,然后感觉自己并不是很熟悉这个,便好好的了解一下. 根据特意的去了解后,发现实际上可以有三种方式来实现init method和destroy method. 要用这两个方法,自然先要知道这两

Spring中Bean初始化及销毁方法(InitializingBean接口、DisposableBean接口、@PostConstruct注解、@PreDestroy注解、以及init-method方法和destroy-method方法)

一. 在Spring中Bean的初始化后以及销毁前的回调方式有: init-method:是指创建bean时调用的方法,注意,不是创建bean的方法. destroy-method:是指销毁bean时调用的方法,同样,不是销毁bean的方法. @PostConstruct注解:在bean实例化和注入后,进行初始化 @PreDestroy:在bean销毁前回调 InitializingBean接口: 查看InitializingBean接口的源码可以发现,只有一个方法,需要pojo继承Initia

spring中afterPropertiesSet方法与init-method配置描述

1. InitializingBean.afterPropertiesSet()Spirng中InitializingBean接口类为bean提供了定义初始化方法的方式,它仅仅包含一个方法:afterPropertiesSet().Bean实现这个接口,在afterPropertiesSet()中编写初始化代码: public class EventEngineImpl implements EventEngine, InitializingBean { private static final

深入源码分析Spring中的构造器注入

# 1. 示例 构造器注入类,分别有三个构造器,一个是无参构造器,一个是注入一个Bean的构造器,一个是注入两个Bean的构造器: public class ConstructorAutowiredTest { private User user; private Role role; public ConstructorAutowiredTest() { } public ConstructorAutowiredTest(User user) { this.user = user; } pub

Spring Boot报错Error creating bean with name &#39;userRepository&#39;: Invocation of init method failed; nested exception

问题:出现UserRePository注入创建失败,一定先检查所有的@注解是否已经标记 问题发现:entity下的实体类上面没有加注解  任何基于hibernate的实体类一定要加上@Entity注解! Spring Boot报错Error creating bean with name 'userRepository': Invocation of init method failed; nested exception 原文地址:https://www.cnblogs.com/my-prog