什么是Spring beans?
Spring beans 是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配,和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中<bean/> 的形式定义。
虎丘bean的方式
方法一:在初始化时保存ApplicationContext对象
方法二:通过Spring提供的utils类获取ApplicationContext对象
方法三:继承自抽象类ApplicationObjectSupport
方法四:继承自抽象类WebApplicationObjectSupport
方法五:实现接口ApplicationContextAware
方法六:通过Spring提供的ContextLoader
bean装配
通过依赖注入把bean组装到一起
自动装配:Spring 容器能够自动装配相互合作的bean,这意味着容器不需要<constructor-arg>和<property>配置,能通过Bean工厂自动处理bean之间的协作。
装配方式:
1.no:默认的方式是不进行自动装配,通过显式设置ref 属性来进行装配。
2.byName:通过参数名自动装配
3.byType:通过参数类型自动装配
4.constructor:这个方式类似于byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
5.autodetect: 优先使用constructor ,失败则byType
Spring注解
@Autowire
其实是使用了byType的Bean装配方式
如何使用:
xml里配置
方式1.
<bean
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
方式2.
<context:annotation-config />
ps:当出现一个接口由多个实现的时候,可以使用 @Quanlifier 来指定要装配的bean
spring bean的作用域
1.singleton : 单例作用域 不是线程安全的
2.prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
3.request:每次请求有一个实例
4.session:在一个HTTP session中,一个bean定义一个实例,该作用域仅在基于web的Spring ApplicationContext情形下有效。
5.global-session:在全局HTTP session中 ,一个bean一个实例,该作用域仅在基于web的Spring ApplicationContext情形下有效。
bean 加载方式
1.applicationcontext上下文,这种加载会一开始就加载进去
2.beanFactory,会在需要的时候 getBean的时候加载
bean 生命周期
1.实例化一个bean
2.按照上下文的属性,对bean进行ioc注入
3.1如果bean实现BeanNameAware的接口,就会对该接口里面的setBeanName进行设置,此处传递的是Spring配置文件中Bean的ID
3.2如果这个Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(),传递的是Spring工厂本身(可以用这个方法获取到其他Bean)
3.3果这个Bean实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文,该方式同样可以实现步骤3.2,但比3.2更好,以为ApplicationContext是BeanFactory的子接口,有更多的实现方法(通过beanFactory的时候没有这一步)
4.是否关联实现了BeanPostProcessor接口,调用前置处理方法
5.如果这个Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法
6.是否关联实现了BeanPostProcessor接口,调用后置处理方法
7.注册必要的Destruction的回调接口
——————————————————
好啦,现在我们可以用这个bean啦
——————————————————
8.用完了这个bean,就不需要了,如果实现DispoableBean接口,那么会调用其实现的destroy方法
9.最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法
不建议使用(建议使用init-method 和 destroy-method ):
InitializingBean和DisposableBean是两个标记接口,为Spring执行时bean的初始化和销毁某些行为时的有用方法。
对于Bean实现 InitializingBean,它将运行 afterPropertiesSet()在所有的 bean 属性被设置之后。
对于 Bean 实现了DisposableBean,它将运行 destroy()在 Spring 容器释放该 bean 之后。
实例:
public class CustomerService implements InitializingBean, DisposableBean
{
String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void afterPropertiesSet() throws Exception {
System.out.println("Init method after properties are set : " + message);
}
public void destroy() throws Exception {
System.out.println("Spring Container is destroy! Customer clean up");
}
init-method 和 destroy-method:
public class CustomerService
{
String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void initIt() throws Exception {
System.out.println("Init method after properties are set : " + message);
}
public void cleanUp() throws Exception {
System.out.println("Spring Container is destroy! Customer clean up");
}
}
xml设置
<bean id="customerService" class="com.yiibai.customer.services.CustomerService"
init-method="initIt" destroy-method="cleanUp">
<property name="message" value="i'm property message" />
</bean>
bean扩展点
在实例化之前可以使用BeanFactoryPostProcessor:可以修改bean的元信息,属性
就是上面的4和6 在初始化之前之后使用BeanPostProcessor:不可以修改。
@Component – 指示自动扫描组件。
@Repository – 表示在持久层DAO组件。
@Service – 表示在业务层服务组件。
@Controller – 表示在表示层控制器组件。
注解的实现都是@Component 不同的命名只是为了区分层
Spring循环依赖
解决方式: 三级缓存
一级缓存singletonObjects
二级缓存earlySingletonObjects
三级缓存singletonFactories
当发生循环依赖的时候。
createBeanInstance之后会调用
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
这里会往3级缓存先提前暴露出这个bean。
然后A在createBeanInstance之后,因为依赖了B,会去找B,发现没存在B,就create。createB的时候依赖了A,去找A。然后在3级缓存里找到了,就自己创建后面的流程了。
但是如果是在构造方法里互相依赖就不行,因为加入singletonFactories三级缓存的前提是执行了构造器