Spring------Bean的装配

Bean的装配

Bean的装配,就是Bean对象的创建,容器根据代码要求创建Bean对象后再传递给代码的过程,称为Bean的装配

Bean的默装配方式

通过getBean()方式从容器中获取指定的Bean实例,容器首先会调用Bean类的无参数构造器,创建空值的实例对象。

示例:
AService.java

package com.bean01;

public interface AService {

	void doSome();
	
}

AServiceImpl.java

package com.bean01;

public class ASereviceImpl implements AService {

	//spring默认的是调用类的无参数构造方法,创建空值对象
	public ASereviceImpl() {
		super();
		System.out.println("ASereviceImpl的无参构造方法");
	}

	@Override
	public void doSome() {
		System.out.println("==--业务方法doSome()--==");
		
	}

}

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对象
    	id:对象名称,唯一值。
    	class:全限定的类名 不能是接口
     -->
     <!-- bean标签的作用等同于
     SomeService someService = new SomeServiceImpl() -->
     <bean id="aService" class="com.bean01.ASereviceImpl" />

</beans>

MyTest.java

package com.bean01;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MyTest {

	/**
	 * spring容器中的对象是什么时间创建的?
	 * 在创建容器对象的时候,会创建配置文件中的所有对象
	 * 优点:一次创建所有对象,在使用getBean()获取对象时速度快
	 * 缺点:占用内存
	 */
	@Test
	public void test01() {
		String configLocation = "com/bean01/applicationContext.xml";
		ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);
		//对象相当于已经存放在了spring的map中 (getBean()源码)
		AService service =  (AService) ctx.getBean("aService");
		service.doSome();
 	}
	
	
}

在这里插入图片描述

容器中Bean的作用域

创建Bean示例的时候,可以通过scope属性,为Bean()指定特定的作用域。

Spring支持5种作用域(主要会用到的有以下4种):

(1)singleton: 单例模式。在Spring容器中,使用singleton定义的Bean将是一个单例的,只有一个实例。默认的作用域就是单例的。
(2)prototype:原型模式。每次使用getBean()方法获取的同一个< bean />的实例都是一个新的实例。
(3)request:对于每次HTTP请求,都将会产生一个不同的Bean实例。
(4)session:对于每个不同的HTTP session,都将产生一个不同的Bean实例。

注意:
对于scope为singleton的单例模式,Bean是在容器被创建时即被装配好了。
对于scope为prototype的原型模式,Bean实例是在代码中使用到该Bean实例时才进行装配的。

示例(单例模式):
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">

    <!-- 
    	定义对象的作用域,指定对象的存在范围和可见性
    	1.singleton 单例,这是默认值,表示在spring容器中对象只有一个
    	 如何指定单例:
    	 			<bean id="xx" class="yyy" scope="singleton" />
    	2.prototype  原型,表示每次使用getBean()都会创建一个新的对象
    	 如何指定原型作用域:
    	 			<bean id="xx" class="yyy" scope="prototype" />
     -->
     <!-- 单例 -->
     
     <bean id="aService" class="com.bean02.ASereviceImpl" scope="singleton" />
     
</beans>

MyTest.java

package com.bean02;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MyTest {

	/**
	 * 单例对象是什么时间创建的?
	 * 创建容器对象的时候,会创建配置文件中的所有对象
	 */
	@Test
	public void test01() {
		String configLocation = "com/bean02/applicationContext.xml";
		ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);
		//单例对象
		AService service1 =  (AService) ctx.getBean("aService");
		AService service2 =  (AService) ctx.getBean("aService");
		
		//判断对象是否为同一个   
		if (service1 == service2) {
			
			System.out.println("service1和service2是同一个对象");
			
		} else {
			
			System.out.println("service1和service2【不是】同一个对象");
			
		}
 	}
	
}

在这里插入图片描述示例(原型模式):
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">

    <!-- 
    	定义对象的作用域,指定对象的存在范围和可见性
    	1.singleton 单例,这是默认值,表示在spring容器中对象只有一个
    	 如何指定单例:
    	 			<bean id="xx" class="yyy" scope="singleton" />
    	2.prototype  原型,表示每次使用getBean()都会创建一个新的对象
    	 如何指定原型作用域:
    	 			<bean id="xx" class="yyy" scope="prototype" />
     --> 
     <!-- 原型 -->
     <bean id="aService" class="com.bean02.ASereviceImpl" scope="prototype" />

</beans>

MyTest.java

package com.bean02;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MyTest {

	/**
	 * 测试原型作用域
	 * 原型作用域的对象创建时间?
	 * 把对象的创建时间延迟到使用对象的时候(调用getBean()之后才创建)
	 */
	@Test
	public void test02() {
		
		String configLocation = "com/bean02/applicationContext.xml";
		ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);
		//原型作用域对象  调用getBean()创建出来到本方法结束,该对象就不存在了 相当于是没有存放在getBean()的map中的
		AService service1 =  (AService) ctx.getBean("aService");
		AService service2 =  (AService) ctx.getBean("aService");
		
		System.out.println("service1: " + service1.hashCode());
		System.out.println("service2: " + service2.hashCode());
		if (service1 == service2) {
			
			System.out.println("service1和service2是同一个对象");
			
		} else {
			
			System.out.println("service1和service2【不是】同一个对象");
			
		}
		
	}
	
	
}

在这里插入图片描述

自定义Bean的生命始末

可以为Bean定制初始化后的生命行为,也可以为Bean定制销毁前的生命行为。
需要在配置文件的< bean/>标签中增加如下属性:

init-method:指定初始化方法的方法名
destroy-method:指定销毁方法的方法名
注:destroy-method实现需要两个条件
(1)Bean为singleton
(2)确保容器关闭。关闭时,接口ApplicationContext没有close方法,但是它的实现类有,所以要将ApplicationContext对象进行强转成其实现类的对象执行close方法

示例:
AServiceImpl.java

package com.bean03;

public class ASereviceImpl implements AService {

	//spring默认的是调用类的无参数构造方法,创建空值对象
	public ASereviceImpl() {
		super();
		System.out.println("ASereviceImpl的无参构造方法");
	}

	@Override
	public void doSome() {
		System.out.println("==--业务方法doSome()--==");
		
	}

	
	//定义bean的生命始末方法
	/**
	 * 初始化方法,作用是创建其他对象,给属性赋值,等同于构造方法的作用
	 */
	public void setUp() {
		
		System.out.println("bean的初始化方法,等同于构造方法的作用");
		
	}
	
	/**
	 * bean销毁之前执行的方法,只要是用来回收资源,释放内存
	 */
	public void tearDown() {
		
		System.out.println("bean销毁之前执行的方法,用来回收资源");
		
	}
}

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的生命始末 可以参与到spring创建对象,和销毁对象的过程中,自定义一些操作
    	1.在代码中定义生命始末的方法,方法的原型是 public void 方法名自定义() {自定义的操作}
    	2.在spring的配置文件中,定义bean对象的时候,指定方法名称
    		<bean id="xx" class="yyy" init-method="bean的初始化方法名称"
    		 destroy-method="bean对象销毁之前执行的方法名称" />
    	两个方法不需要同时存在
     -->
     <bean id="aService" class="com.bean03.ASereviceImpl" init-method="setUp"
     	destroy-method="tearDown" />
     

</beans>

MyTest.java

package com.bean03;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MyTest {


	@Test
	public void test01() {
		String configLocation = "com/bean03/applicationContext.xml";
		ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);
		//单例对象
		AService service =  (AService) ctx.getBean("aService");
		
		service.doSome();
		
		/**
		 * AService service = new AServiceImpl();
		 * service.setUp();
		 */
		
		/**
		 * 执行销毁方法
		 * 1.关闭容器
		 * 2.对象得是单例的 
		 * 因为是单例的对象存放在容器之中 原型的没有存放在容器中,所以会无法执行销毁方法
		 */
		((ClassPathXmlApplicationContext)ctx).close();  //Map
 	}
	
}

在这里插入图片描述

结束语

我喜欢吃肉,我不是英雄,我只做我想做的事,保护我想要保护的人而已。 ——路飞《海贼王》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值