Spring
Posted 小企鹅推雪球!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring相关的知识,希望对你有一定的参考价值。
文章目录
Spring Bean的作用域
- 在Spring中定义一个bean时,必须声明该bean的作用域的选项
- 例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 prototype
- ,如果想让 Spring 在每次需要时都返回同一个bean实例,应该声明 bean 的作用域的属性为 singleton。
- Spring 框架支持以下五个作用域,分别为 singleton、prototype、request、session 和 global session,
- singleton作用域:在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值
- prototype作用域:每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()
- request作用域:每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
- session作用域:同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境
singleton作用域
- singleton 是默认的作用域
- 当将一个 bean 定义设置为 singleton 作用域的时候,Spring IoC 容器只会创建该 bean 定义的唯一实例。
- Singleton 是单例类型,就是在创建起容器时就同时自动创建了一个 bean 的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。
<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="singleton">
<!-- collaborators and configuration for this bean go here -->
</bean>
Spring singleton 作用域样例
- 在创建项目的 src 文件夹中创建一个包 com.tutorialspoint
- 使用 Add External JARs 选项,添加所需的 Spring 库,
- 在 com.tutorialspoint 包中创建 Java 类 HelloWorld 和 MainApp。
- 在 src 文件夹中创建 Beans 配置文件 Beans.xml。
- 创建的所有 Java 文件和 Bean 配置文件的内容
HelloWorld.java 文件的内容
package com.tutorialspoint;
public class HelloWorld {
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
}
MainApp.java 文件的内容:
package com.tutorialspoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld objA = (HelloWorld) context.getBean("helloWorld");
objA.setMessage("I'm object A");
objA.getMessage();
HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
objB.getMessage();
}
}
singleton 作用域必需的配置文件 Beans.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-3.0.xsd">
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld"
scope="singleton">
</bean>
</beans>
创建源代码和 bean 配置文件完成后,我们就可以运行该应用程序并将输出以下信息
Your Message : I'm object A
Your Message : I'm object A
Spring-prototype 作用域
- 当一个 bean 的作用域为 Prototype,表示一个 bean 定义对应多个对象实例
- Prototype 作用域的 bean 会导致在每次对该 bean 请求(将其注入到另一个 bean 中,或者以程序的方式调用容器的 getBean() 方法)时都会创建一个新的 bean 实例。
- Prototype 是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象
- 注意:对有状态的 bean 应该使用 prototype 作用域,而对无状态的bean则应该使用 singleton 作用域。
- 为了定义 prototype 作用域,你可以在 bean 的配置文件中设置作用域的属性为 prototype
<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="prototype">
<!-- collaborators and configuration for this bean go here -->
</bean>
Spring-prototype 作用域样例
prototype 作用域必需的配置文件 Beans.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-3.0.xsd">
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld"
scope="prototype">
</bean>
</beans>
Spring Bean生命周期
- 当一个bean被实例化时,可能需要执行一些初始化使它转换成可用状态,当 bean 不再需要,并且从容器中移除时,可能需要做一些清除工作。
- 为了定义安装和拆卸一个 bean,需要声明带有 init-method 和/或 destroy-method 参数的bean,
- init-method 属性指定一个方法,在实例化 bean 时,立即调用该方法。同样,destroy-method 指定一个方法,只有从容器中移除 bean 之后,才能调用该方法
- Bean的生命周期可以表达为:Bean的定义——Bean的初始化——Bean的使用——Bean的销毁
Spring Bean生命周期样例
第一:HelloWorld.java文件内容
package com.tutorialspoint;
public class HelloWorld {
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
public void init(){
System.out.println("Bean is going through init.");
}
public void destroy(){
System.out.println("Bean will destroy now.");
}
}
第二: MainApp.java 文件的内容。需要注册一个在 AbstractApplicationContext 类中声明的关闭 hook 的 registerShutdownHook() 方法。它将确保正常关闭,并且调用相关的 destroy 方法。
package com.tutorialspoint;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
context.registerShutdownHook();
}
}
第三:init 和 destroy 方法必需的配置文件 Beans.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-3.0.xsd">
<bean id="helloWorld"
class="com.tutorialspoint.HelloWorld"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
</beans>
创建源代码和 bean 配置文件完成后,运行该应用程序,输出
Bean is going through init.
Your Message : Hello World!
Bean will destroy now.
默认的初始化和销毁方法
- 如果有太多具有相同名称的初始化或者销毁方法的 Bean,不需要在每一个 bean 上声明初始化方法和销毁方法
- 框架使用 元素中的 default-init-method 和 default-destroy-method 属性提供了灵活地配置销毁多个同名的Bean
<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-3.0.xsd"
default-init-method="init"
default-destroy-method="destroy">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
</beans>
Spring Bean后置处理器
- Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理。
- BeanPostProcessor 接口定义回调方法,可以实现该方法来提供自己的实例化逻辑,依赖解析逻辑等。也可以在 Spring 容器通过插入一个或多个 BeanPostProcessor 的实现来完成实例化,配置和初始化一个bean之后实现一些自定义逻辑回调方法。
- 可以配置多个 BeanPostProcessor 接口,通过设置 BeanPostProcessor 实现的 Ordered 接口提供的 order 属性来控制这些 BeanPostProcessor 接口的执行顺序。
- BeanPostProcessor 可以对 bean(或对象)实例进行操作,这意味着 Spring IoC 容器实例化一个 bean 实例,然后 BeanPostProcessor 接口进行它们的工作。
- ApplicationContext 会自动检测由 BeanPostProcessor 接口的实现定义的 bean,注册这些 bean 为后置处理器,然后通过在容器中创建 bean,在适当的时候调用它。
- 自定义的 BeanPostProcessor 接口实现类中,要实现以下的两个抽象方法
BeanPostProcessor.postProcessBeforeInitialization(Object, String) 和 BeanPostProcessor.postProcessAfterInitialization(Object, String) 和,注意命名要准确
否则会出现: “ The type InitHelloWorld must implement the inherited abstract method BeanPostProcessor.postProcessBeforeInitialization(Object, String) ”之类的错误
Spring Bean后置处理器样例
- 在 ApplicationContext 的上下文中编写,注册和使用 BeanPostProcessor
- 第一步:创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包 com.tutorialspoint
- 第二步:使用 Add External JARs 选项,添加所需的 Spring 库
- 第三步;在 com.tutorialspoint 包中创建 Java 类 HelloWorld、InitHelloWorld和 MainApp
- 第四步:在 src 文件夹中创建 Beans 配置文件 Beans.xml
HelloWorld.java 文件的内容:
package com.tutorialspoint;
public class HelloWorld {
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
public void init(){
System.out.println("Bean is going through init.");
}
public void destroy(){
System.out.println("Bean will destroy now.");
}
}
实现 BeanPostProcessor 在任何 bean 的初始化的之前和之后输入该 bean 的名称,可以在初始化 bean 的之前和之后实现更复杂的逻辑,因为有两个访问内置 bean 对象的后置处理程序的方法
InitHelloWorld.java 文件的内容:
package com.tutorialspoint;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;
public class InitHelloWorld implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeforeInitialization : " + beanName);
return bean; // you can return any other object as well
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("AfterInitialization : " + beanName);
return bean; // you can return any other object as well
}
}
MainApp.java 文件的内容:需要注册一个在 AbstractApplicationContext 类中声明的关闭 hook 的 registerShutdownHook() 方法。它将确保正常关闭,并且调用相关的 destroy 方法。
package com.tutorialspoint;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
context.registerShutdownHook();
}
}
init 和 destroy 方法需要的配置文件 Beans.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-3.0.xsd">
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
<bean class="com.tutorialspoint.InitHelloWorld" />
</beans>
创建源代码和 bean 配置文件完成后,运行该应用程序,输出
BeforeInitialization : helloWorld
Bean is going through init.
AfterInitialization : helloWorld
Your Message : Hello World!
Bean will destroy now.
Spring Bean定义继承
- bean 定义可以包含很多的配置信息,包括构造函数的参数,属性值,容器的具体信息例如初始化方法,静态工厂方法名,等等。
- 子 bean 的定义继承父定义的配置数据。子定义可以根据需要重写一些值,或者添加其他值。
- Spring Bean 定义的继承与 Java 类的继承无关,但是继承的概念是一样的
- 可以定义一个父 bean 的定义作为模板和其他子 bean 就可以从父 bean 中继承所需的配置。
- 当使用基于 XML 的配置元数据时,通过使用父属性,指定父 bean 作为该属性的值来表明子 bean 的定义。
Spring Bean定义继承样例
- 创建一个名称为 SpringExample 的项目,并且在创建项目的 src 文件夹中创建一个包 com.tutorialspoint。
- 使用 Add External JARs 选项,添加所需的 Spring 库
- 在 com.tutorialspoint 包中创建 Java 类 HelloWorld、HelloIndia 和 MainApp。
- 在 src 文件夹中创建 Beans 配置文件 Beans.xml。
第一;配置文件 Beans.xml
- 在Beans.xml配置文件中我们定义有两个属性 message1 和 message2 的 “helloWorld” bean。
- 使用 parent 属性把 “helloIndia” bean 定义为 “helloWorld” bean 的孩子。这个子 bean 继承 message2 的属性,重写 message1 的属性,并且引入一个属性 message3。
<?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-3.0.xsd">
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld">
<property name="message1" value="Hello World!"/>
<property name="message2" value="Hello Second World!"/>
</bean>
<bean id="helloIndia" class="com.tutorialspoint.HelloIndia" parent="helloWorld">
<property name="message1" value="Hello India!"/>
<property name="message3" value="Namaste India!"/>
</bean>
</beans>
第二: HelloWorld.java 文件的内容:
package com.tutorialspoint;
public class HelloWorld {
private String message1;
private String message2;
public void setMessage1(String message){
this.message1 = message;
}
public void setMessage2(String message){
this.message2 = message;
}
public void getMessage1(){
System.out.println("World Message1 : " + message1);
}
public void getMessage2(){
System.out.println("World Message2 : " + message2);
}
}
第三: HelloIndia.java 文件的内容:
package com.tutorialspoint;
public class HelloIndia {
private String message1;
private String message2;
private String message3;
public void setMessage1(String message){
this.message1 = message;
}
public void setMessage2(String message){
this.message2 = message;
}
public void setMessage3(String message){
this.message3 = message;
}
public void getMessage1(){
System.out.println("India Message1 : " + message1);
}
public void getMessage2(){
System.out.println("India Message2 : " + message2);
}
public void getMessage3(){
System.out.println("India Message3 : " + message3);
}
}
MainApp.java 文件的内容:
package com.tutorialspoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld objA = (HelloWorld) context.getBean("helloWorld");
objA.getMessage1();
objA.getMessage2();
HelloIndia objB = (HelloIndia) context.getBean("helloIndia");
objB.getMessage1();
objB.getMessage2();
objB.getMessage3();
}
}
创建源代码和 bean 配置文件完成后,运行程序,输出以下信息
World Message1 : Hello World!
World Message2 : Hello Second World!
India Message1 : Hello India!
India Message2 : Hello Second World!
India Message3 : Namaste India!
**注意:**创建 “helloIndia” bean 的同时并没有传递 message2,但是由于 Bean 定义的继承,所以它传递了 message2。
Bean定义模板
- 创建一个 Bean 定义模板,可以被其他子 bean 定义使用
- 在定义一个 Bean 定义模板时,不应该指定类的属性,而应该指定带 true 值的抽象属性
<?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-3.0.xsd">
<bean id="beanTeamplate" abstract="true">
<property name="message1" value="Hello World!"/>
<property name="message2" value="Hello Second World!"/>
<property name="message3" value="Namaste India!"/>
</bean>
<bean id="helloIndia" class="com.tutorialspoint.HelloIndia" parent="beanTeamplate">
<property name="message1" value="Hello India!"/>
<property name="message3" value="Namaste India!"/>
</bean>
</beans>
- 父 bean 自身不能被实例化,因为它是不完整的,而且它也被明确地标记为抽象的。当一个定义是抽象的,它仅仅作为一个纯粹的模板 bean 定义来使用的,充当子定义的父定义使用。
以上是关于Spring的主要内容,如果未能解决你的问题,请参考以下文章
Spring boot:thymeleaf 没有正确渲染片段
What's the difference between @Component, @Repository & @Service annotations in Spring?(代码片段
spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段
Spring Rest 文档。片段生成时 UTF-8 中间字节无效 [重复]
解决spring-boot启动中碰到的问题:Cannot determine embedded database driver class for database type NONE(转)(代码片段