目录
一、配置bean概要(绿色的是主要演示的)
二、Bean的配置形式(这里介绍通过XML形式)和配置方式:
三、Spring容器:
Spring提供了两种类型的IOC容器的实现
ApplicationContext的主要实现类
四、依赖注入的方式:
属性注入:
构造方法注入:
案例分析(演示构造器注入的方法):
1.一个简单的构造器注入
2.用index和type确定注入的属性
配置形式:基于XML文件的形式、基于注解的方式
Bean的配置方式:通过全类名(反射),通过工厂方式(静态工厂方式和实例工厂方法)、FactoryBean
IOC容器的BeanFactory&ApplicationContext概述
依赖注入的方法:属性注入和构造器注入
注入属性值细节
自动转配
bean之间的关系:继承和依赖
bean的作用域:singleton;prototype;web环境作用域
使用外部属性文件
spEL
IOC容器中bean的生命周期
Spring4.x新特性,泛型的依赖注入
class中:bean的全类名,通过反射的方式在IOC容器中创建bean,所以要求bean中必须要有无参的构造器;
//创建一个无参的构造器
public HelloWord() {
System.out.println("正在初始化一个构造器");
}
id:标识容器中的bean,id唯一。
在SpringIOC容器读取Bean配置创建Bean实例之前,必须对他进行实例化。只有在容器实例化之后,才可以从IOC容器中获取bean实例并使用。
1、BeanFactory:IOC容器的基本实现。
2、ApplicationContext提供了更多的高级特性。是BeanFactory的子接口。
两者之间进行比较:BeanFactory是Spring框架的基础设施,面向Spring本身;ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都直接使用ApplicationContext,而不是底层的BeanFactory。但是无论使用BeanFactory还是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中这样配置,就会报错。
报的异常是:
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的属性值或依赖的对象。属性注入使用
通过构造方法注入Bean的属性值或依赖的对象,他保证了Bean实例在实例化后就可以使用。构造器注入在
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,如下:
然后在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]
根据上面的案例,我们可以看到,Car的前三个属性一次被注入了值,那么如果我们载定义一个构造器,这个构造器的属性是brand、corp、maxSpeed,那么执行的话会出现什么情况呢,我们在Car中加入:
public Car(String brand, String corp, int maxSpeed) {
super();
this.brand = brand;
this.corp = corp;
this.maxSpeed = maxSpeed;
}
将xml修改为:
再来执行一下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中的代码改造一下:
我们在执行一下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来确定给容器中注入哪一个属性的值。