Spring学习(2)——bean的配置

目录

 

一、配置bean概要(绿色的是主要演示的)

二、Bean的配置形式(这里介绍通过XML形式)和配置方式:

三、Spring容器:

Spring提供了两种类型的IOC容器的实现

ApplicationContext的主要实现类

四、依赖注入的方式:

属性注入:

构造方法注入:

案例分析(演示构造器注入的方法):

1.一个简单的构造器注入

2.用index和type确定注入的属性


一、配置bean概要(绿色的是主要演示的)

配置形式:基于XML文件的形式、基于注解的方式

Bean的配置方式:通过全类名(反射,通过工厂方式(静态工厂方式和实例工厂方法)、FactoryBean

IOC容器的BeanFactory&ApplicationContext概述

依赖注入的方法:属性注入和构造器注入

注入属性值细节

自动转配

bean之间的关系:继承和依赖

bean的作用域:singleton;prototype;web环境作用域

使用外部属性文件

spEL

IOC容器中bean的生命周期

Spring4.x新特性,泛型的依赖注入

二、Bean的配置形式(这里介绍通过XML形式)和配置方式:

class中:bean的全类名,通过反射的方式在IOC容器中创建bean,所以要求bean中必须要有无参的构造器

	//创建一个无参的构造器
	public HelloWord() {
		System.out.println("正在初始化一个构造器");
	}

id:标识容器中的bean,id唯一。

	<!-- 配置bean -->
	<bean id="helloword" class="com.atguigu.spring.beans.HelloWord">
		<property name="name" value="spring"></property>
	</bean>

三、Spring容器:

在SpringIOC容器读取Bean配置创建Bean实例之前,必须对他进行实例化。只有在容器实例化之后,才可以从IOC容器中获取bean实例并使用。

  • Spring提供了两种类型的IOC容器的实现

1、BeanFactory:IOC容器的基本实现。

2、ApplicationContext提供了更多的高级特性。是BeanFactory的子接口。

两者之间进行比较:BeanFactory是Spring框架的基础设施,面向Spring本身;ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都直接使用ApplicationContext,而不是底层的BeanFactory。但是无论使用BeanFactory还是ApplicationContext何种类型,配置文件都是相同的。

  • ApplicationContext的主要实现类

有两个:ClassPathXmlApplicationContext和FileSystemXmlApplicationContext

ClassPathXmlApplicationContext:从类路径下面加载配置文件;

FileSystemXmlApplicationContext:从文件系统中加载配置文件;

ConfigurableApplicationContext扩展于ApplicationContext,新增加了两个主要的实现方法:refresh()和close(),让ApplicationContext有启动,刷新和关闭上下文的能力。

ApplicationContext在初始化上下文的时候就实现了所有的单例bean。

WebApplicationContext是专门为WEB应用而准备的,他允许从相对于WEB根目录的路径中完成初始化工作。

从IOC容器中获取Bean

调用ApplicationContext的getBean()方法。

HelloWord hw=(HelloWord) cxt.getBean("helloword");
HelloWord hw=cxt.getBean(HelloWord.class);//这种方式也行,但是不建议,因为这种方式是利用类型返回IOC容器中的bean,但要求IOC容器中必须只能有一个该类型的Bean。

注意一下:

如果用HelloWord hw=cxt.getBean(HelloWord.class);这种方式,利用类型返回IOC容器中的Bean,但要求IOC容器中必须只能有一个该类型的Bean,如果在XML中这样配置,就会报错。

	<bean id="helloword" class="com.atguigu.spring.beans.HelloWord">
		<property name="name" value="spring"></property>
	</bean>
	<bean id="helloword1" class="com.atguigu.spring.beans.HelloWord">
		<property name="name" value="spring"></property>
	</bean>

报的异常是:

Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.atguigu.spring.beans.HelloWord] is defined: expected single matching bean but found 2: helloword,helloword1
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:290)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1125)
	at com.atguigu.spring.beans.Main.main(Main.java:21)

所以说HelloWord hw=cxt.getBean(HelloWord.class);是不建议使用的。

四、依赖注入的方式:

Spring支持3中依赖注入的方式:属性注入、构造器注入、工厂方法注入(很少使用,不推荐)

  • 属性注入

属性注入是通过setter方法注入Bean的属性值或依赖的对象。属性注入使用<property>元素,使用name属性执行Bean的属性名称,value属性或者<value>属性子节点指定属性值。属性注入是实际应用中最常用的注入方式。

	<bean id="helloword" class="com.atguigu.spring.beans.HelloWord">
		<property name="name" value="spring"></property>
	</bean>
  • 构造方法注入

通过构造方法注入Bean的属性值或依赖的对象,他保证了Bean实例在实例化后就可以使用。构造器注入在<constructor-arg>元素里面声明属性,<constructor-arg>中没有name属性。

  • 案例分析(演示构造器注入的方法):

1.一个简单的构造器注入

public class Car {
	private String brand;
	private String corp;
	private double price;
	private int maxSpeed;
	
	public Car(String brand, String corp, double price) {
		super();
		this.brand = brand;
		this.corp = corp;
		this.price = price;
	}
	

	@Override
	public String toString() {
		return "Car [brand=" + brand + ", corp=" + corp + ", price=" + price + ", maxSpeed=" + maxSpeed + "]";
	}
	

}

通过constructor-arg构造器注入的方式在xml中添加bean,如下:

	<!-- 通过构造方法配置bean的属性 -->
	<bean id="car" class="com.atguigu.spring.beans.Car">
		<constructor-arg value="Audi"></constructor-arg>
		<constructor-arg value="Gansu"></constructor-arg>
		<constructor-arg value="300000"></constructor-arg>
	</bean>

然后在Main中编写执行代码:

	public static void main(String[] args) {
		Main main=new Main();
		main.testConstructorArg();
	}

	/**
	 * 通过构造器注入bean的值
	 */
	private void testConstructorArg() {
		ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
		Car car = (Car) cxt.getBean("car");
		System.out.println("Car: " + car);
	}

这是一个最简单的构造器注入,下面是执行结果:

Car: Car [brand=Audi, corp=Gansu, price=300000, maxSpeed=0]

2.用index和type确定注入的属性

根据上面的案例,我们可以看到,Car的前三个属性一次被注入了值,那么如果我们载定义一个构造器,这个构造器的属性是brand、corp、maxSpeed,那么执行的话会出现什么情况呢,我们在Car中加入:

	public Car(String brand, String corp, int maxSpeed) {
		super();
		this.brand = brand;
		this.corp = corp;
		this.maxSpeed = maxSpeed;
	}

将xml修改为:

	<!-- 通过构造方法配置bean的属性 -->
	<bean id="car" class="com.atguigu.spring.beans.Car">
		<constructor-arg value="Audi"></constructor-arg>
		<constructor-arg value="Gansu"></constructor-arg>
		<constructor-arg value="300000"></constructor-arg>
	</bean>
		<!-- 通过构造方法配置bean的属性 -->
	<bean id="car1" class="com.atguigu.spring.beans.Car">
		<constructor-arg value="Audi"></constructor-arg>
		<constructor-arg value="Gansu"></constructor-arg>
		<constructor-arg value="180"></constructor-arg>
	</bean>

再来执行一下Main:

	public static void main(String[] args) {
		Main main=new Main();
		main.testConstructorArg();
	}

	/**
	 * 通过构造器注入bean的值
	 */
	private void testConstructorArg() {
		ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
		Car car = (Car) cxt.getBean("car");
		System.out.println("Car: " + car);
		
		Car car1 = (Car) cxt.getBean("car1");
		System.out.println("Car1: " + car1);
	}

可以看到执行的结果中,第一个Car对象被注入了brand、corp、price,这是第一个构造器的,好像没什么问题,但是Car对象被注入了brand、corp、parice,那么我们的第二个构造器的参数是brand、corp、maxSpeed啊:

Car: Car [brand=Audi, corp=Gansu, price=300000.0, maxSpeed=0]
Car1: Car [brand=Audi, corp=Gansu, price=180.0, maxSpeed=0]

这样并不是我们想要的,我想要在Car1中被注入的对象是:brand、corp、maxSpeed,这样我们就需要利用constructor注入中的index和type来区分属性了,index是在构造器注入中属性值的索引,type是构造器主图中属性值的类型。我们将xml中的代码改造一下:

	<!-- 通过构造方法配置bean的属性 -->
	<bean id="car" class="com.atguigu.spring.beans.Car">
		<constructor-arg value="Audi" index="0"></constructor-arg>
		<constructor-arg value="Gansu" index="1"></constructor-arg>
		<constructor-arg value="300000" index="2"></constructor-arg>
	</bean>
		<!-- 通过构造方法配置bean的属性 -->
	<bean id="car1" class="com.atguigu.spring.beans.Car">
		<constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
		<constructor-arg value="Gansu" type="java.lang.String"></constructor-arg>
		<constructor-arg value="180" type="int"></constructor-arg>
	</bean>

我们在执行一下Main,结果是:

Car: Car [brand=Audi, corp=Gansu, price=300000.0, maxSpeed=0]
Car1: Car [brand=Audi, corp=Gansu, price=0.0, maxSpeed=180]

我们可以根据iconstructor注入中的index和type来确定给容器中注入哪一个属性的值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值