Spring框架(二)

一、控制反转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 requiredType) 根据指定的类型返回一个Bean,客户端无需自己进行类型转换,但是如果全局配置文件中没有或多于一个Bean存在将会抛出异常。

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

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

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

3.3、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定义。class属性指定的类要求写完整的包名和类名。

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

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

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

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

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

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

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

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

Bean的加载:

默认情况下,我们使用

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

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

对单例的对象,可以手动设置其 来设置其延迟初始化,前提是这个对象没有被其他的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标签的子标签有、。
 <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标签的子标签有,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还允许用户定制自己的作用域。作用域利用标签中的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注入配置,减少配置文件的长度。自动装配通过配置标签的 autowire 属性来改变自动装配方式。

(1)default:表示使用默认的自动装配,默认的自动装配需要在标签中使用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();}
}

Spring框架(二)相关推荐

  1. Spring框架(二) 底层架构核心概念解析-四万字你值得一看

    本篇文章将对Spring底层的一些概念做一些简单的分析 , 也是为了方便后续在阅读源码的时候更加的方便 BeanDefintion BeanDefintion是一个接口 , 它表示一个Bean的定义 ...

  2. 阿里三面让我现场改造Spring框架,明天带他去爬山!

    作为一个Java程序员,提到开源框架,Spring无疑是绕不过去的门槛,相信大家对它都不陌生,或多或少都用过. 但是如果谈到改造Spring框架,实现它的自定义扩展,以及大厂面试必问的源码,很多人就会 ...

  3. 深入学习Spring框架(二)- 注解配置

    1.为什么要学习Spring的注解配置? 基于注解配置的方式也已经逐渐代替xml.所以我们必须要掌握使用注解的方式配置Spring. 关于实际的开发中到底使用xml还是注解,每家公司有着不同的使用习惯 ...

  4. 【SSM框架 二】Spring

    文章目录 二.Spring 1.简介 2.IOC理论思想 3.Hello Spring 4.IOC创建对象的方式 4.1 无参构造构造器注入 4.2 有参构造器注入 5.Spring的配置 5.1 别 ...

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

    Java学习笔记-Day64 Spring 框架(二) 一.控制反转IOC和依赖注入DI 1.控制反转IOC 2.依赖注入DI 3.Spring IOC容器 3.1.简介 3.2.实现容器 3.2.获 ...

  6. Spring 框架源码(二) 事务Transaction源码深度解析

    目录 一.基于xml形式开启Transaction 1. 创建数据库user 2. 创建一个maven 项目 3. 通过xml形式配置事务 1) 创建Spring 命名空间 2) 开启事务配置 3) ...

  7. spring框架学习(二)依赖注入

    spring框架为我们提供了三种注入方式,分别是set注入,构造方法注入,接口注入.接口注入不作要求,下面介绍前两种方式. 1,set注入 采用属性的set方法进行初始化,就成为set注入. 1)给普 ...

  8. osgi框架和spring区别_BATJ面试必会之 Spring 篇(二)

    原文链接: https://howtodoinjava.com/interview-questions/top-spring-interview-questions-with-answers/ 翻译: ...

  9. Spring框架知识复习之二

    Spring使用注解对Bean进行管理 1 使用注解需配置aop相关xsd文件的约束和命名空间 xsd文件名为:spring-aop-4.2.xsd 2 注解组件扫描配置 示例如下:base-pack ...

最新文章

  1. ubuntu 搭建webrtc环境
  2. c++读取txt中每行的数据到数组中
  3. NLPCC:预训练在小米的推理优化落地
  4. 设计模式--解析器(Interpreter)模式
  5. boost::function30的用法实例
  6. java dvd集合框架_JAVA 集合框架
  7. [Python] 探索性编程与idleX
  8. 基础数据类型转换过程中注意事项
  9. android widget 开发实例 : 桌面便签程序的实现具体解释和源代码 (上)
  10. 计算机一级考试基本操作是什么,计算机一级等级考试试题基本操作总结
  11. jQuery,JS实现自定义鼠标右键菜单
  12. VS隐藏菜单插件 Hide Main Menu
  13. hosts文件位置在哪里
  14. 捡到的文物应该归谁最好
  15. 读《别做正常的傻瓜》
  16. Windows XP控制台图解
  17. 这个世界的本源不是物质,而是物质背后的基本秩序-柏拉图
  18. 大snbsp;汪小菲nbsp;闪婚
  19. C++编程基础(1)-C中的malloc/free和C++中的new/delete
  20. 使用BoundsChecker查找内存泄露

热门文章

  1. DC/DC:闭环控制的升压(Boost)变换电路原理设计及实验仿真
  2. html链接文字样式,修改word文档中超链接文字样式的操作方法
  3. python调用接口查询_python调用接口查询 顺丰单号 物流信息
  4. python之父面试谷歌_Python之父Guido Rossum:打造Google第三大開發語言-经管之家官网!...
  5. iPhone港版、美版、日版、国行,到底有什么区别?看完涨知识
  6. Linux下查看根目录各文件内存占用情况
  7. 高考数学知识点:数列压轴小题秒杀技巧
  8. centos7升级gcc版本,无需手动下载源码编译
  9. 网小鱼Java的bug小集锦0014
  10. 【听】自私的基因,生物进化的本质