spring(bean初始化、销毁、注入,作用域)
IOC:控制反转,也称为依赖注入(DI)。这是一个过程。通常我们需要一个对象的时候,是主动创建对象,并且主动传入到需要使用该对象的地方。而IOC则是由容器创建对象,注入到我们需要使用该对象的位置,两者相比,一个主动,一个被动,被动的则是称为依赖注入(控制反转,由主动创建改为被动注入)。IOC容器读取配置元数据配置、组装、并实例化bean。配置元数据有3种方式 web.xml方式:可...
IOC:控制反转,也称为依赖注入(DI)。这是一个过程。通常我们需要一个对象的时候,是主动创建对象,并且主动传入到需要使用该对象的地方。而IOC则是由容器创建对象,注入到我们需要使用该对象的位置,两者相比,一个主动,一个被动,被动的则是称为依赖注入(控制反转,由主动创建改为被动注入)。IOC容器读取配置元数据配置、组装、并实例化bean。配置元数据有3种方式
- web.xml方式:可用<bean id="" class=""></bean>,其中 id不是必须的。它是一个属性,用于标识bean的定义,class属性为bean的,使用类的全限定名。该<bean/>标签内还可以有多个属性,具体请查看文档。
- java注释:可用@Configuration、@Bean、@Import、@DependsOn。
- java代码:可用@Configuration、@Bean、@Import、@DependsOn。
bean:构成应用程序骨干,并由Spring IOC管理的对象称之为Bean。bean也是一个组装、实例化并由Spring IOC管理的一个对象。bean 的命名约定遵循 java 变量命名的约定。bean 还可以定义别名,如:
<!-- 定义bean -->
<bean id="userController" class="com.xh.spring.project.controller.user.UserController"></bean>
<!-- 别名标签中name属性为定义bean时的id,alias是为该bean指定的别名 -->
<alias name="userController" alias="user"/>
如果使用JAVA注释的方式定义bean,则@Bean标签内可以指定名称。bean 默认的创建方式是调用该类的构造器创建的。
也可通过静态工厂方法来创建实例 bean,这种方法指定的初始化方法(必须无参数)、销毁方法(必须无参数)、必须在要被创建bean实例的类当中,如:
public class TestBean {
public TestBean() {
System.out.println(this + "-------------------------------------------constructor method call()......");
}
public void initMethod() {
System.out.println(this + "调用----init method call()......");
}
public void destroy() {
System.out.println(this + "调用 --------destroy method call()......");
}
}
工厂方法(参数可选):
public static TestBean getTestBean(String name){
System.out.println("=========================factory method call()......" + name);
return new TestBean();
}
配置文件:
<!-- factory-method指定静态工厂方法,class指定静态方法所在的类 init(bean创建之后调用)以及destroy(销毁时调用)分别指定初始化与销毁方法
工厂方法可以有参数,参数通过这种方式可以指定 <bean><constructor-arg index="0" value="zhangsan"/></bean>-->
<bean id="testBean" factory-method="getTestBean"
class="com.xh.spring.project.controller.test.BeanFactory"
init-method="initMethod"
destroy-method="destroy">
<constructor-arg index="0" value="zhangsan"/>
</bean>
也可使用注解的方式:
package com.xh.spring.project.controller.test;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;
@Component("testBean")
public class TestBean {
public TestBean() {
System.out.println(this + "-------------------------------------------constructor method call()......");
}
@PostConstruct
public void initMethod() {
System.out.println(this + "调用----init method call()......");
}
@PreDestroy
public void destroy() {
System.out.println(this + "调用 --------destroy method call()......");
}
}
还可以利用已有的 bean 对象来创建新的 bean 对象,只需要在配置文件当中配置
<!-- factory-bean指定用哪个bean来创建新的bean,factory-method指定用bean中的哪个方法来创建(方法必须位于
factory-bean指定的bean的具体类当中,方法为 实例方法) -->
<bean id="testOtherBean" factory-bean="testBean" factory-method="getTestOtherBean"></bean>
testBean中的内容:
package com.xh.spring.project.controller.test;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;
public class TestBean {
public TestBean() {
System.out.println(this + "-------------------------------------------constructor method call()......");
}
public void initMethod() {
System.out.println(this + "调用----init method call()......");
}
public void destroy() {
System.out.println(this + "调用 --------destroy method call()......");
}
public TestOtherBean getTestOtherBean() {
System.out.println("----------------------------------factory method call()......");
return new TestOtherBean();
}
}
bean的初始化、销毁、回调函数
上例中,在创建 bean 的时候,指定了初始化、销毁 bean 时的回调函数。上例是设置单个 bean 的回调函数。
还可以为所有的bean设置指定的初始化、销毁、的回调方法。只需要在顶层 <beans> 标签当中加入,default-init-method、default-destroy-method,利用该标签指定初始化回调函数、销毁回调函数的函数名。Spring IOC容器会识别该属性,当一个 bean 被创建组装时,如果该 bean 有这样一个方法,它会在适当的时间调用这个方法(Spring 容器保证一个配置好的初始化回调函数在一个 bean 被提供了所有的依赖关系之后被立即调用。这意味着AOP拦截器还没有被应用到 bean,因为目标 bean 首先被创建,然后才会使用代理)。
Spring 有3个控制 bean 生命周期的选项,InitializingBean、DisposableBean回调接口,init()和destrot()方法,以及 @PostConstruct @PreDestroy注释。
如果为同一个bean配置了多个生命周期机制,并且多个机制都具有相同的方法名,那么这些方法,将只执行一次。如果多个生命周期机制使用不同的初始化方法,调用顺序为(以初始化回调为例,初始化回调、销毁回调的顺序是一样的):
用注释的方法,@PostConstruct
afterPropertiesSet(方法),这是InitializingBean接口中的方法。
自定义配置的init()方法。
依赖注入
依赖注入有2种
- 基于构造器的依赖注入
- 基于setter的依赖注入
还有很多基于上面2种混合使用的注入案例,可以查看Spring官方文档学习。
构造器注入(推荐使用):
package com.xh.spring.project.controller.test;
public class DemoBean {
private String name;
private int age;
public DemoBean(String name, int age) {
this.name = name;
this.age = age;
}
}
在注入具体值时,使用构造器注入时,如果用type属性,那么顺序将不再那么重要,spring将会自动的寻找匹配的类型,将具体值注入进去。有些类型,如:string 则必须要全限定类名,否则无法注入进去
<bean id="demoBean" class="com.xh.spring.project.controller.test.DemoBean">
<constructor-arg type="int" value="29"/>
<constructor-arg type="java.lang.String" value="zhangsan"/>
</bean>
如果使用index属性,那么书写顺序将严格按照构造器当中参数的顺序书写,否则将会报错。索引属性 index 从 0 开始
<bean id="demoBean" class="com.xh.spring.project.controller.test.DemoBean">
<constructor-arg index="0" value="zhangsan"/>
<constructor-arg index="1" value="29"/>
</bean>
还可以使用构造器当中具体的属性名称充当构造注入时的 name 属性
<bean id="demoBean" class="com.xh.spring.project.controller.test.DemoBean">
<constructor-arg name="age" value="29"/>
<constructor-arg name="name" value="zhangsan"/>
</bean>
还可以使用 p 命名空间,以及 c 命名空间 来进行注入,当使用 p 时,注入基本值,使用 p:属性名=“值”, 注入其他bean属性时 p:属性名-ref=“bean名称”。c 命名空间与之类似
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/mydb"
p:username="root"
p:password="masterkaoli"/>
</beans>
<bean id="bar" class="x.y.Bar"/>
<bean id="baz" class="x.y.Baz"/>
<!-- traditional declaration -->
<bean id="foo" class="x.y.Foo">
<constructor-arg ref="bar"/>
<constructor-arg ref="baz"/>
<constructor-arg value="foo@bar.com"/>
</bean>
<!-- c-namespace declaration -->
<bean id="foo" class="x.y.Foo" c:bar-ref="bar" c:baz-ref="baz" c:email="foo@bar.com"/>
Spring容器在容器创建时验证每个 bean 的配置,在实际创建 bean 之前,bean 属性本身不会被实例化,bean 是单例的,(默认的设置是)是预先实例化,在创建容器的时候创建的。也可以在请求的该bean的时候创建(懒惰初始化)。
spring的自动装配有4种模式
- 默认的。也就是直接在定义bean的时候,在配置文件当中利用 ref 属性指定需要装备进去的bean。
- 按名称。也就是在使用注解注入的时候,指定需要注入的 bean 的名称,spring 会自动去寻找指定名称的 bean 进行装配
- 按类型。当需要装配时,如果IOC容器当中只有一个符合需要注入的 bean 类型,则允许按类型自动装配。如果存在多个,则抛异常。如果没有匹配的bean,则不做任何事。
- 类似于byType,但适用于构造函数参数。如果容器中没有一个构造函数参数类型的bean,则会引发致命错误。
bean的作用域
创建一个 bean 也是基于配置文件,创建一个该 bean 定义所对应的类的实例。创建 bean 的实际操作由 spring 操作,但是bean的各种属性配置,则有我们来实现。而作用域也是如此。spring 支持7种作用域。
- singleton:每个 Spring IOC 容器将单个 bean 定义作用域为单个对象实例。这个单例 bean 被缓存在这样的 sigleton bean 缓存池中,所有对该bean的请求都会从该缓存池中获取该 bean 对象并返回。
- ptototype:每次获取都将产生一个新的 bean 实例。spring 不在管理原型 bean 的整个生命周期,但 spring 在创建 bean 的时候 依然会调用初始化生命周期的回调方法,但是却不在调用配置的销毁生命周期的方法。bean对象 的使用者必须自己清理 bean 的引用,释放其所持有的资源。
- requet:将单个bean定义作用与单个HTTP请求的生命周期,也就是说每个HTPP请求都有自己的bean实例。这个实例是在单个 bean 定义的后面创建的。只有在网络感知的Spring的上下文中才有效。
- session
- globalSession
- application
- websocket
spring相对来说
是很主要单独
更多推荐
所有评论(0)