Java学习笔记-Day64 Spring 框架(二)

  • 一、控制反转IOC和依赖注入DI
    • 1、控制反转IOC
    • 2、依赖注入DI
    • 3、Spring IOC容器
      • 3.1、简介
      • 3.2、实现容器
      • 3.2、获取Bean对象
      • 3.4、IOC容器的操作
  • 二、Spring Bean
  • 三、注入方法和注入类型
    • 1、注入方法
    • 2、注入类型
  • 四、Bean的作用域
  • 五、自动装配autowire
  • 六、单元测试JUnit
    • 1、JUnit4
    • 2、JUnit5
    • 3、JUnit4-Spring5
    • 4、JUnit5-Spring5
  • 七、Spring Bean的生命周期
    • 1、生命周期
    • 2、代码案例


一、控制反转IOC和依赖注入DI


控制反转和依赖注入是对同一件事情的不同描述,从某个方面讲,就是它们描述的角度不同。控制反转是说不需要程序员管理和控制bean,是解耦的目的,而依赖注入是手段。IOC是指让生成类的方式由传统方式反过来,即程序员不调用new运算符生成,需要类的时候则是由Spring等框架注入(DI)。

1、控制反转IOC


IOC(Inversion of Control)控制反转:控制反转不是什么技术,而是一种设计思想。IOC是一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试。有了IOC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。其实IOC对编程带来的最大改变不是从代码上,而是从思想上,发生了主从换位的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IOC思想中,应用程序就变成被动的,应用程序被动的等待IOC容器来创建并注入它所需要的资源了。

控制反转IOC是指控制权由应用程序转到外部容器,即控制权的转移。在Java开发中,IOC意味着将设计好的对象交给Spring容器控制,而不是传统的在程序内部直接控制。

类的一些属性 (例如UserService中的userDao成员属性)原来是由当前类(UserService)自己控制其实例化,现在则是由Spring利用接口来控制。可以使用xml或者注解来进行相关配置,spring会根据配置和约定,对对象进行实例化和属性装配。

2、依赖注入DI


DI(Dependency Injection)依赖注入:一些成员属性(例如UserService中的userDao成员属性) 依赖Spring容器来注入,组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。

依赖注入DI是spring 的核心机制,可以使Spring的bean以配置文件组织在一起,而不是硬编码方式耦合,耦合性相对来降低了。另外,注入是使用配置文件来实现,这样修改非常的方便。

3、Spring IOC容器

3.1、简介


Spring IOC 容器的代表就是org.springframework.beans包中的BeanFactory接口,BeanFactory接口提供了 IOC 容器最基本功能;而org.springframework.context包下的ApplicationContext接口扩展了BeanFactory,还提供了与Spring AOP集成、国际化处理、事件传播及提供不同层次的context实现 (如针对web应用的WebApplicationContext)。简单说, BeanFactory提供了IoC容器最基本功能,而 ApplicationContext 则增加了更多支持企业级功能支持。ApplicationContext完全继承BeanFactory,因而BeanFactory所具有的语义也适用于ApplicationContext。

3.2、实现容器


• XmlBeanFactory:BeanFactory实现,提供基本的IOC容器功能,可以从classpath或文件系统等获取资源;
(1)方式一:

  File file = new File("apppicationContext.xml");Resource resource = new FileSystemResource(file);BeanFactory context = new XmlBeanFactory(resource);

(2)方式二:

 Resource resource = new ClassPathResource("apppicationContext.xml");     BeanFactory context = new XmlBeanFactory(resource);


• ClassPathXmlApplicationContext:ApplicationContext实现,从classpath获取配置文件;

 BeanFactory context = new ClassPathXmlApplicationContext("apppicationContext.xml");


• FileSystemXmlApplicationContext:ApplicationContext实现,从文件系统获取配置文件。

 BeanFactory context = new FileSystemXmlApplicationContext("classpath:apppicationContext.xml");

3.2、获取Bean对象


通过ApplicationContext接口的getBean方法从Spring容器中获取Bean对象。

① 通过 Bean对象的id或者name来获取:
Object getBean(String name) 根据名称返回一个Bean,客户端需要自己进行类型转换;参数name可以是bean的属性id的值或者是name的值。

 Blog blog = (Blog) context.getBean("blog1");


② 通过 Bean对象的类名来获取:
T getBean(Class<T> requiredType) 根据指定的类型返回一个Bean,客户端无需自己进行类型转换,但是如果全局配置文件中没有或多于一个Bean存在将会抛出异常。

 Blog blog = context.getBean(Blog.class);


③ 通过 Bean对象的id或者name和类名来获取:
T getBean(String name, Class<T> requiredType) 根据名称和指定的类型返回一个Bean,客户端无需自己进行类型转换,如果类型转换失败,容器抛出异常。返回的是指定名称同时指定类型的bean对象。

 Blog blog = context.getBean("blog1", Blog.class);

3.4、IOC容器的操作


① 配置文件的准备工作:在配置文件applicationContext.xml中声明Bean,也就是为Bean配置元数据。

<?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 class="com.etc.blog.entity.Blog" name="blog1" scope="prototype"><property name="id" value="1"></property><property name="title" value="特里克"></property><property name="content" value="特里克....."></property></bean>
</beans>

② IOC容器解析元数据: IoC容器的Bean Reader读取并解析配置文件,根据定义生成BeanDefinition配置元数据对象,IoC容器根据BeanDefinition进行实例化、配置及组装Bean。

③ 实例化IOC容器:由客户端实例化容器,获取需要的Bean。

package com.etc.blog.test;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.etc.blog.entity.Blog;public class test {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");Blog blog1 = context.getBean("blog1", Blog.class);System.out.println("blog1="+blog1);}
}

二、Spring Bean


Spring IOC容器目的就是管理Bean,这些Bean将根据配置文件中的Bean定义进行创建,而Bean定义在容器内部由BeanDefinition对象表示,该定义主要包含以下信息:

  • 全限定类名(FQN):用于定义Bean的实现类。限定类名就是类名全称,带包路径的用点隔开,例如: java.lang.String。非限定类名也叫短名,就是平时说的类名,不带包的,例如:String。
  • Bean行为定义:这些定义了Bean在容器中的行为;包括作用域(单例、原型创建)、是否惰性初始化及生命周期等;
  • Bean创建方式定义:说明是通过构造器还是工厂方法创建Bean;
  • Bean之间关系定义:即对其他bean的引用,也就是依赖关系定义,这些引用bean也可以称之为同事bean或依赖bean,也就是依赖注入。
<?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 class="com.etc.blog.entity.Blog" id="blog1"><property name="id" value="1"></property><property name="title" value="特里克"></property></bean>
</beans>

Bean命名约定:Bean的命名遵循XML命名规范,但最好符合Java命名规范,由字母、数字、下划线组成,而且应该养成一个良好的命名习惯, 比如采用驼峰式,即第一个单词首字母开始,从第二个单词开始首字母大写开始,这样可以增加可读性。

1、<bean> 标签主要用来进行Bean定义。class属性指定的类要求写完整的包名和类名。

 <bean class="com.etc.blog.entity.Blog" id="blog1"></bean>

2、<alias> 标签用于定义Bean别名的。alias属性表示别名,name表示已经定义Bean的name。

 <bean class="com.etc.blog.entity.Blog" name="blog1"></bean><alias alias="otherBlogName" name="blog1"></alias>

3、<property > 标签用于进行Setter注入,也就是给实体类中的某个属性赋值,会调用对应实体类的Setter方法。name属性代表属性的名字,value属性代表属性的值。

 <property name="title" value="特里克"></property>

4、<import> 标签用于导入其他配置文件的Bean定义,这是为了加载多个配置文件,当然也可以把这些配置文件构造为一个数组(new String[] {“applicationContext1.xml“, “applicationContext2.xml”})传给ApplicationContext实现进行加载多个配置文件。这两种方式都是通过调用Bean Definition Reader 读取Bean定义,内部实现没有任何区别。<import>标签可以放在<beans>中的任何位置,没有顺序关系。

 <import resource="applicationContext2.xml"></import>

注意:标签中的属性id与name作用是一样,区别在于id中不可以含有特殊字符,而name中可以有特殊字符;id是确定该bean的唯一属性,而name可以指定一个或者多个名称,各个名称之间用逗号或分号分开。后面的为bean的别名。

Bean的加载:

默认情况下,我们使用

 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

Spring容器就会自动初始化所有的单例<bean scope=”singleton”>的bean。但是如果是<bean scope=”prototype”>则不会自动初始化,而是等使用的时候才实例化,也就是调用context.getBean方法的时候。

对单例的对象,可以手动设置其 <bean lazy-init=”true” >来设置其延迟初始化,前提是这个对象没有被其他的bean引用。

三、注入方法和注入类型

1、注入方法


(1)Setter注入
Setter注入就是在bean中使用setXX方法进行注入,因此需要在bean类中,成员属性需要setXX方法如下:

  • Bean类
public class Blog implements Serializable {private int id;private String title;private String content;/* private Author author; */public Blog(int id, String title, String content) {super();System.out.println("blog有参构造 setId..."+id);this.id = id;this.title = title;this.content = content;}public Blog() {super();System.out.println("blog无参构造 "+"id="+id+","+"title="+title);}public int getId() {return id;}public void setId(int id) {System.out.println("setId..."+id);this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}@Overridepublic String toString() {return "Blog [id=" + id + ", title=" + title + ", content=" + content + "]";}  }
  • Spring全局配置文件
 <bean class="com.etc.blog.entity.Blog" name="blog1"><!-- 属性赋值,在bean类中有setter方法 --><property name="id" value="1"></property><property name="title" value="特里克"></property><property name="content" value="特里克....."></property></bean>


(2)构造方法注入
构造方法注入就是在bean中使用有参构造方法进行注入,在bean类中需要有成员属性作为参数的构造方法。

  • Bean类
public class Blog implements Serializable {private int id;private String title;private String content;/* private Author author; */public Blog(int id, String title, String content) {super();System.out.println("blog有参构造 setId..."+id);this.id = id;this.title = title;this.content = content;}public Blog() {super();System.out.println("blog无参构造 "+"id="+id+","+"title="+title);}public int getId() {return id;}public void setId(int id) {System.out.println("setId..."+id);this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}@Overridepublic String toString() {return "Blog [id=" + id + ", title=" + title + ", content=" + content + "]";}  }
  • Spring的全局配置文件
 <bean class="com.etc.blog.entity.Blog" id="blog1"><!-- 通过有参构造方法赋值 --><constructor-arg name="id" value="1"></constructor-arg><constructor-arg name="title" value="第一种方式"></constructor-arg><constructor-arg name="content" value="第一种方式。。。"></constructor-arg></bean><bean class="com.etc.blog.entity.Blog" id="blog2"><!-- index为0代表第一个参数--><constructor-arg index="0" value="2"></constructor-arg><constructor-arg index="1" value="第二种方式"></constructor-arg><constructor-arg index="2" value="第二种方式。。。"></constructor-arg></bean> -->

2、注入类型


(1)简单属性的注入

在bean中存在简单属性时的注入方式。

<?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 class="com.etc.blog.entity.Blog" name="blog1"><property name="id"><value>123</value></property><property name="title" value="特里克"></property><property name="content" value="特里克....."></property></bean>
</beans>


(2)其他数据类型的属性注入

Spring不仅能注入简单类型数据,还能注入自定义对象、集合(Collection、无序集合Set、有序集合List)类型数据、数组(Array)类型数据、字典(Map)类型数据、Properties类型数据。

  • List集合
    注入的属性类型为List时,在 property 标签中使用<list></list>表示集合,list标签的子标签有<value></value><ref bean="对象名"></ref>
 <property name="list"><list><value>1</value><value>aaa</value><value>55.55</value></list></property>
 <property name="list"><list><ref bean="blog1"></ref><ref bean="blog2"></ref></list></property>

  • Map字典
    注入的属性类型为Map时,在 property 标签中使用<map></map>表示字典,map标签的子标签有<entry ></entry >,entry标签的属性有key(键)、value(值)、key-ref(类型为对象的键)、value-ref(类型为对象的值)。
 <property name="map"><map><entry key="1" value="值1"></entry><entry key="2" value="值2"></entry></map></property>
 <property name="map"><map><entry key="1" value-ref="blog3"></entry><entry key="2" value-ref="blog4"></entry></map></property>
 <property name="map"><map><entry key-ref="blog1" value-ref="blog3"></entry><entry key-ref="blog2" value-ref="blog4"></entry></map></property>

  • 自定义对象
    注入的属性类型为自定义对象时,需要使用 property 标签的ref属性引用对象,ref属性的值为对象的id或者name。
 <bean class="com.etc.blog.entity.Blog" name="blog1"><property name="id" value="1"></property><property name="title" value="特里克"></property><property name="content" value="特里克....."></property><property name="author" ref="author1"></property></bean><bean class="com.etc.blog.entity.Author" name="author1"><property name="id" value="1"></property><property name="name" value="小明"></property></bean>

四、Bean的作用域


作用域(scope),在面向对象程序设计中一般指对象或变量之间的可见范围。而在Spring容器中是指其创建的Bean对象相对于其他Bean对象的请求可见范围。

Spring提供 singleton 和 prototype 两种基本作用域,另外提供 request 、 session 、 global session 三种web作用域,Spring还允许用户定制自己的作用域。作用域利用<bean></bean>标签中的scope属性来指定。

scope属性的值:
(1)singleton(单例):默认作用域,每次取出的Bean对象都是同一个Bean对象。
(2)prototype(原型):懒加载,在使用getBean方法调用Bean对象时,才会创建Bean对象,每次获取的bean对象时,都会重新创建一个新的Bean对象。
(3)request:一次请求一个bean定义对应一个实例(web相关)
(4)session:一个session定义对应一个实例(web相关)
(5)globalsession类似于session作用域,只是其用于portlet环境的web应用。如果在非portlet环境将视为session作用域(web相关)

 <bean class="com.etc.blog.entity.Blog" name="blog1" scope="prototype"><property name="id"><value>123</value></property><property name="title" value="特里克"></property><property name="content" value="特里克....."></property></bean>

五、自动装配autowire


自动装配就是指由Spring来自动地注入依赖对象。

Spring的装配支持 no 、 byName 、 byType 、 constructor 四种自动装配,默认是 no(不支持自动装配)。

自动装配的好处是减少构造器注入和setter注入配置,减少配置文件的长度。自动装配通过配置<bean></bean>标签的 autowire 属性来改变自动装配方式。

(1)default:表示使用默认的自动装配,默认的自动装配需要在<bean></bean>标签中使用default-autowire属性指定,其支持 no 、 byName 、 byType 、 constructor 四种自动装配。
(2)no:意思是不支持自动装配,必须明确指定依赖。
(3)byType:按照类型来进行装配,但是要求同一个类型的bean在xml中只能有一个.调用setter方法.
(4)byName:通过设置Bean定义属性autowire=“byName”,意思是根据名字进行自动装配,只能用于setter注入。

 <bean class="com.etc.blog.entity.Blog" name="blog1" autowire="byName"><property name="id"><value>123</value></property><property name="title" value="特里克"></property><property name="content" value="特里克....."></property></bean>

六、单元测试JUnit

1、JUnit4


可以使用Junit完成简单的单元测试,在一个方法上增加一个@Test 注解,要注意大小写,同时要将junit4.jar添加到构建路径中来。Run as Junt test 运行这个方法的时候,如果出现了绿色,表示单元测试成功,如果出现红色,则表示单元测试失败,程序代码有问题。

@Before:org.junit.Before
@Test:org.junit.Test
@After:org.junit.After


import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.FileSystemXmlApplicationContext;import com.etc.blog.entity.Blog;public class TestJunit4 {BeanFactory context;@Beforepublic void before() {System.out.println("before");context = new FileSystemXmlApplicationContext("classpath:applicationContext4.xml");}@Testpublic void test1() {System.out.println("test1");Blog blog1 = context.getBean("blog1",Blog.class);System.out.println("blog1="+blog1);}@Testpublic void test2() {System.out.println("test2");Blog blog2 = context.getBean("blog2",Blog.class);System.out.println("blog2="+blog2);}@Afterpublic void after() {System.out.println("after");}
}

2、JUnit5


可以使用Junit完成简单的单元测试,在一个方法上增加一个@Test 注解,要注意大小写,同时要将junit5.jar添加到构建路径中来。Run as Junt test 运行这个方法的时候,如果出现了绿色,表示单元测试成功,如果出现红色,则表示单元测试失败,程序代码有问题。

@BeforeEach:org.junit.jupiter.api.BeforeEach
@Test:org.junit.jupiter.api.Test
@AfterEach:org.junit.jupiter.api.AfterEach


import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.FileSystemXmlApplicationContext;import com.etc.blog.entity.Blog;public class TestJunit5 {BeanFactory context;@BeforeEachpublic void before() {System.out.println("beforeEach");context = new FileSystemXmlApplicationContext("classpath:applicationContext4.xml");}@Testpublic void test1() {System.out.println("test1");Blog blog1 = context.getBean("blog1",Blog.class);System.out.println("blog1="+blog1);}@Testpublic void test2() {System.out.println("test2");Blog blog2 = context.getBean("blog2",Blog.class);System.out.println("blog2="+blog2);}@AfterEachpublic void after() {System.out.println("afterEach");}
}

3、JUnit4-Spring5


(1)添加spring-test.jar到构建路径。
(2)编写测试类,使用注解配合JUnit代码。

  • @RunWith(SpringJUnit4ClassRunner.class):让测试运行于Spring测试环境。
  • @RunWith(SpringRunner.class):让测试运行于Spring测试环境。
  • @ContextConfiguration(locations= {"/applicationContext.xml"}):加载Spring配置文件。
  • @Autowired:自动装配。
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;import com.etc.blog.entity.Blog;//@RunWith(SpringJUnit4ClassRunner.class)
@RunWith(SpringRunner.class)
@ContextConfiguration(locations= {"/applicationContext3.xml"})
public class TestJunit4Spring5 {@AutowiredBlog blog;@Testpublic void test1() {System.out.println("blog="+blog);}
}

4、JUnit5-Spring5


(1)添加spring-test.jar到构建路径。
(2)编写测试类,使用注解配合JUnit代码。

  • @SpringJUnitConfig(locations="/applicationContext.xml"):@SpringJUnitConfig = @ContextConfiguration +@RunWith
  • @Qualifier(value=“blog1”):通过这个注解,表明了哪个实现类才是我们所需要的,添加@Qualifier注解,需要注意的是@Qualifier的参数名称为已经定义的Bean名称。
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import com.etc.blog.entity.Blog;//@SpringJUnitConfig =  @ContextConfiguration +@RunWith
@SpringJUnitConfig(locations="/applicationContext4.xml")
public class TestJunit5Spring5 {@Autowired@Qualifier(value="blog1")Blog blog;@Testpublic void test1() {System.out.println("blog="+blog);}
}

七、Spring Bean的生命周期

1、生命周期


(1)Bean的装配。
Bean的装配是指将java对象转换为spring Bean的过程。
注意:Spring支持xml方式、java代码方式、自动装配等。

 <bean class="com.etc.blog.entity.Blog" name="blog1"><property name="id" value="1"></property><property name="title" value="测试生命周期"></property><property name="content" value="测试生命周期。。。。"></property></bean>

(2)加载Spring的全局配置文件并实例化。
加载配置文件applicationContext.xml并实例化,在java代码中可以通过ClassPathXmlApplicationContext()方法来加载,当Bean的作用域为singleton时,加载配置文件的同时就会实例化对象,当Bean的作用域为prototype时,需要等待java代码中调用applicationContext的getBean()方法获取bean时,才会实例化对象。

 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext5.xml");Blog blog1 = context.getBean("blog1", Blog.class);

(3)Bean属性注入
Bean属性注入,即为Bean对象的属性赋值,底层采用反射方式注入bean,通过实体类的Setter方法实现。

 public void setId(int id) {System.out.println("setId..."+id);this.id = id;}public void setTitle(String title) {this.title = title;}public void setContent(String content) {this.content = content;}

(4) 实体类实现BeanNameAware接口,并实现接口中的setBeanName方法。获取bean的id或name。

 @Overridepublic void setBeanName(String arg0) {System.out.println("3、Blog setBeanName方法 获取bean id/name :"+arg0);}

(5)实体类实现BeanFactoryAware接口,并实现接口中的setBeanFactory方法。获取bean工厂。

 @Overridepublic void setBeanFactory(BeanFactory arg0) throws BeansException {System.out.println("4、Blog setBeanFactory方法 获取bean工厂 :"+arg0);}

(6)实体类实现ApplicationContextAware接口,并实现接口中的setApplicationContext方法。获取应用上下文。

 @Overridepublic void setApplicationContext(ApplicationContext arg0) throws BeansException {System.out.println("5、Blog setApplicationContext方法 获取应用上下文 :"+arg0);}

(7)实现后置处理器,创建一个实现BeanPostProcessor接口的自定义类,并实现接口中的postProcessBeforeInitialization和postProcessAfterInitialization方法,该过程是通过AOP方式实现的。要在Spring配置文件中编写该自定义类的Bean。此处会调用postProcessBeforeInitialization方法。

public class TestBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("调用postProcessBeforeInitialization方法");return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("调用postProcessAfterInitialization方法");return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}
}
 <bean class="com.etc.blog.entity.TestBeanPostProcessor" id="processor1"></bean>

(8)实体类实现InitializingBean接口,并实现接口中的afterPropertiesSet方法,获取初始化方法。

 @Overridepublic void afterPropertiesSet() throws Exception {System.out.println("6、Blog afterPropertiesSet方法 获取初始化方法");}

(9)调用自定义初始化方法init-method。
① 在配置文件的对应的bean标签中添加属性 init-method=“init_method”。

 <bean class="com.etc.blog.entity.Blog" id="blog1" init-method="init_method"><property name="id" value="1"></property><property name="title" value="测试数据标题"></property></bean>

② 在实体类中创建init_method方法。

 public void init_method() {System.out.println("7、Blog init_method方法");}

(10)调用Bean后置处理器的postProcessAfterInitialization方法。

(11)此处需要使用AbstractApplicationContext.registerShutDownHook() 关闭容器,如果不关闭,我们无法看到destory销毁的两个方法,这里不算生命周期的一部分。

 context.registerShutdownHook();

(12)实体类实现DisposableBean接口,并实现接口中的destroy方法。

 @Overridepublic void destroy() throws Exception {System.out.println("8、Blog destroy方法");}

(13) 调用自定义销毁方法destroy-method方法。
① 在配置文件的对应的bean标签中添加属性 destroy-method=“destroy_method”。

 <bean class="com.etc.blog.entity.Blog" id="blog1" init-method="init_method" destroy-method="destroy_method"><property name="id" value="1"></property><property name="title" value="测试数据标题"></property></bean>

② 在实体类中创建destroy_method方法。

 public void destroy_method() {System.out.println("9、Blog destroy_method方法");}

2、代码案例

  • applicationContext.xml
<?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 class="com.etc.blog.entity.Blog" id="blog1" init-method="init_method" destroy-method="destroy_method"><property name="id" value="1"></property><property name="title" value="测试数据标题"></property></bean><bean class="com.etc.blog.entity.TestBeanPostProcessor" id="processor1"></bean>
</beans>

  • Blog.java
package com.etc.blog.entity;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;public class Blog implements BeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean {private int id;private String title;public Blog(int id, String title) {super();this.id = id;this.title = title;}public Blog() {super();System.out.println("1、Blog 无参构造方法(实例化)");}public int getId() {return id;}public void setId(int id) {System.out.println("2、Blog setId方法(属性注入)");this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}@Overridepublic String toString() {return "Blog [id=" + id + ", title=" + title + "]";}@Overridepublic void setBeanName(String arg0) {System.out.println("3、Blog setBeanName方法 获取bean id/name :"+arg0);}@Overridepublic void setBeanFactory(BeanFactory arg0) throws BeansException {System.out.println("4、Blog setBeanFactory方法 获取bean工厂 :"+arg0);}@Overridepublic void setApplicationContext(ApplicationContext arg0) throws BeansException {System.out.println("5、Blog setApplicationContext方法 获取应用上下文 :"+arg0);}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("6、Blog afterPropertiesSet方法 获取初始化方法");}public void init_method() {System.out.println("7、Blog init_method方法");}@Overridepublic void destroy() throws Exception {System.out.println("8、Blog destroy方法");}public void destroy_method() {System.out.println("9、Blog destroy_method方法");}
}

  • TestLifeCycle.java
package com.etc.blog.test;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.etc.blog.entity.Blog;public class TestLifeCycle {public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext4.xml"); Blog blog1 = context.getBean("blog1",Blog.class);context.registerShutdownHook();}
}

Java学习笔记-Day64 Spring 框架(二)相关推荐

  1. Spring框架学习笔记(1) ---[spring框架概念 , 初步上手使用Spring , 控制反转 依赖注入初步理解 ]

    spring官网 -->spring官网 spring5.3.12–>spring-framework 在线文档 --> Spring 5.3.12 文章目录 1.Spring概论 ...

  2. Java学习笔记3——集合框架

    文章目录 1 集合的概念 2 Collection体系集合 Collection父接口 3 List接口与实现类 List接口 List实现类 ArrayList Vector LinkedList ...

  3. 黑马Java学习笔记之-----集合框架

    ---------------------- android培训.java培训.期待与您交流! ---------------------- 一.概述: Java的集合类是一种特别有用的工具类,它可以 ...

  4. Java学习笔记——类集框架简介

    Java类集框架 类集指的就是一套动态对象数组的实现方案,在实际开发之中没有任何一项开发可以离开数组,但是传统的数组实现起来非常的繁琐.而且长度是其致命伤,正是因为长度的问题,传统的数组是不能大范围使 ...

  5. java学习笔记--黑马徐老师二

    153 file文件 package File;import java.io.File;/*** 学会创建file对象,定位操做系统的文件*/ public class FileDemo {publi ...

  6. 学习笔记下载Spring框架

    地址:http://repo.springsource.org/libs-release-local/org/springframework/ 选择spring模块.版本,下载*****dist.zi ...

  7. java mvc框架代码_JAVA技术学习笔记:SpringMVC框架(内附入门程序开发代码)

    原标题:JAVA技术学习笔记:SpringMVC框架(内附入门程序开发代码) JavaEE体系结构包括四层,从上到下分别是应用层.Web层.业务层.持久层.Struts和SpringMVC是Web层的 ...

  8. Java学习笔记二:数据类型

    Java学习笔记二:数据类型 1. 整型:没有小数部分,允许为负数,Java整型分4种:int short long byte 1.1 Int最为常用,一个Int类型变量在内存中占用4个字节,取值范围 ...

  9. 【Java学习笔记之二十六】深入理解Java匿名内部类

    在[Java学习笔记之二十五]初步认知Java内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意 ...

最新文章

  1. Linux驱动框架之framebuffer驱动框架
  2. [Head First设计模式]饺子馆(冬至)中的设计模式——工厂模式
  3. Mybatis的修改列与重命名
  4. matlab氢原子杂化轨道,网络版原子和分子结构可视化程序的开发
  5. centos7无GUI情况安装Xvfb、selenium、chrome
  6. Android 字母导航条实现
  7. GIMP教程 2 文字工具
  8. 电工与电子技术基础【3】
  9. 利用基准电压效正Vcc做参考电压的ADC采样计算方法
  10. 计算机无法进去系统,电脑开机后进不了系统的解决方法步骤图
  11. 领导力的21个法则-盖子法则
  12. 三立期货:掌财社重大事项停牌是利好吗?一般停多久?
  13. 数学建模重要算法简介及算法实现
  14. Spark 报错Incompatible equality constraint: String and T2
  15. sql server获取库名,表名
  16. 反向传播算法推导、激活函数、梯度消失与爆炸
  17. java spark 二进制_spark数据源操作
  18. 下载Wikidata并转成TXT文档
  19. java基础语法-day31回顾集合类、I/O流
  20. 手机生产日期查询方法

热门文章

  1. ylbtech-自信:自信
  2. 【论文翻译】iBFS: Concurrent Breadth-First Search on GPUs
  3. 开源jquery特效
  4. Android 手机屏幕分辨率
  5. Kafka消费过程分析
  6. Java用calculate来,calculate_关于calculate的一些短语
  7. 8款样式新颖的jQueryCSS3网页菜单
  8. 数字类型以及类型转换
  9. 【杂记】NOIP前的挣扎『更新中』
  10. flask错误sqlalchemy.exc.IntegrityError: (pymysql.err.IntegrityError) 1452