org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘com.runsstudio.bean.Person’ available: expected single

1
2
3
4
5
6
7
8
9
public void test02(){
Person bean = ioc.getBean(Person.class);
System.out.println(bean.toString());
/*
* NoUniqueBeanDefinitionException:
* No qualifying bean of type
* 'com.runsstudio.bean.Person' available:
* expected single*/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<bean id="person01" class="com.runsstudio.bean.Person">
<property name="name" value="菜龙"/>
<property name="email" value="220@qq.com"></property>
<property name="QQ" value="1165"></property>
<property name="gender" value="male"></property>
<property name="flag" value="false"></property>
</bean>
<bean id="person02" class="com.runsstudio.bean.Person">
<property name="name" value="强禹"/>
<property name="email" value="233@qq.com"></property>
<property name="QQ" value="2333"></property>
<property name="gender" value="male"></property>
<property name="flag" value="false"></property>
</bean>

0 通过有参构造器赋值

1
2
3
4
5
6
7
<bean id="person03" class="com.runsstudio.bean.Person">
<!--调用有参构造器创建对象并赋值-->
<constructor-arg name="name" value="张放"></constructor-arg>
<constructor-arg name="QQ" value="2222"></constructor-arg>
<constructor-arg name="email" value="fdsk"></constructor-arg>
<constructor-arg name="gender" value="男"></constructor-arg>
</bean>
1
2
3
4
5
6
7
8
/**
* 通过构造器来给bean赋值
*/
@Test
public void test03(){
Person person03 = ioc.getBean("person03", Person.class);
System.out.println(person03.toString());
}

1 通过P名称空间为bean赋值:用来防止标签重复

名称空间:在XML中 名称空间是为了防止重复的

1
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

使用p名称空间,需要导入xmlns:p=”http://www.springframework.org/schema/p"

2 各种复杂的赋值

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 测试为各种属性赋值
*/
@Test
public void test07(){
ApplicationContext ioc=new ClassPathXmlApplicationContext("IOCTest2.xml");
Person person07 = ioc.getBean("person01", Person.class);
Car car=ioc.getBean("car02",Car.class);
System.out.println(person07.toString());
System.out.println(person07.getName()==null);
System.out.println(car==person07.getCar());//true 引用的
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<bean id="person01" class="com.runsstudio.bean.Person">
<property name="name">
<!--复杂标签的赋值都在property里赋值,给name赋值null-->
<null></null>
</property>
<property name="car" >
<!--第一种方式:直接也可以放在这里面-->
<bean id="car01" class="com.runsstudio.bean.Car">
<property name="carName" value="宝马"></property>
<property name="price" value="1000"></property>
</bean>
</property>
<property name="carList" ref="car02">

</property>

</bean>
<!--第二种方式 引用-->
<bean id="car02" class="com.runsstudio.bean.Car">
<property name="carName" value="宏碁"></property>
<property name="price" value="100"></property>
</bean>

3 级联属性

1
2
3
4
5
6
7
<!--级联属性赋值:属性的属性-->
<bean class="com.runsstudio.bean.Person" id="person04">
<!--为car赋值的时候改变下价格-->
<property name="car" ref="car02"></property>
<!--级联属性可以修改属性的属性,但是1修改都修改-->
<property name="car.price" value="300"></property>
</bean>
1
2
3
4
5
6
7
        Car car=ioc.getBean("car02",Car.class);
Car car1 = person04.getCar();
System.out.println(car);
System.out.println(car1);//
//输出:
//Car{carName='宏碁', price=300}
//Car{carName='宏碁', price=300}

4 parent 继承关系

1
2
3
4
5
6
7
8
9
10
11
12
<!--parent:制定当前bean配置信息继承与那个,不是真的有继承关系-->
<bean id="person01" class="com.runsstudio.bean.Person" >

<property name="name" value="菜龙"/>
<property name="email" value="220@qq.com"></property>
<property name="QQ" value="1165"></property>
<property name="gender" value="male"></property>
<property name="flag" value="false"></property>
</bean>
<bean id="person02" class="com.runsstudio.bean.Person" parent="person01">
<property name="name" value="强禹"/>
</bean>
1
2
3
4
5
6
7
8
9
10
11
12
13
    @Test
public void test07(){
ApplicationContext ioc=new ClassPathXmlApplicationContext("IOCTestExtends.xml");
Person person01 = ioc.getBean("person01", Person.class);
Person person02 = ioc.getBean("person02", Person.class);
System.out.println(person01);
System.out.println(person02);
}
/*
输出
Person{name='菜龙', email='220@qq.com', QQ=1165, gender='male', flag=false, car=null, carList=null, maps=null, properties=null}
Person{name='强禹', email='220@qq.com', QQ=1165, gender='male', flag=false, car=null, carList=null, maps=null, properties=null}
*/

5 ABSTRACT 抽象

可以在创建person的时候指定abstract属性 即abstract=true
这个时候如果获取实例会抛org.springframework.beans.factory.BeanIsAbstractException

6 bean之间的依赖

bean的创建顺序是按照xml中从上到下的

bean的创建顺序可以改变

可以在配置xml的时候 指定depends-on属性决定bean的创建顺序

7 bean 的作用域,分别创建单实例和多实例的bean

bean默认是单实例的。但是也可以指定多个实例

<bean id="car" class="com.runsstudio.bean.Car" scope="prototype"></bean>

prototype:多实例的

  • 启动的时候不会创建多实例bean
  • 在get Bean的时候创建Bean
1
2
3
Car car = ioc.getBean("car", Car.class);
Car car2 = ioc.getBean("car", Car.class);
System.out.println(car==car2);//false

singleton:单实例的

  • 在容器启动完成之前就已经创建好对象,保存在容器中了
  • 任何时候获取都是获取之前创建好的那个

8 利用工厂的方法创建实例

bean的框架就是利用反射new出来的bean实例

  • 静态工厂:工厂本身不用创建对象;通过静态方法调用 对象=工厂类.工厂方法名()

  • 实例工厂:工厂本身需要创建对象 工厂类 工厂对象=new 工厂类(); 工厂对象.getAirPlane(“”);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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="car01" class="com.runsstudio.factory.CarStaticFactory" factory-method="getCar">
<!--方法指定参数-->
<constructor-arg name="carName" value="红旗"></constructor-arg>
<constructor-arg name="price" value="20000"></constructor-arg>
</bean>
<!--实例工厂:首先创建工厂,然后指定实例
1. 创建实例工厂
2. 配置要创建的bean对象使用工厂中的哪个工厂方法-->
<bean id="carInstanceFactory" class="com.runsstudio.factory.CarInstanceFactory" ></bean>
<bean id="car02" class="com.runsstudio.bean.Car" factory-bean="carInstanceFactory" factory-method="getCar">
<constructor-arg name="type" value="宝马马"></constructor-arg>
</bean>


</beans>

9 Factory工厂类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.runsstudio.factory;

import com.runsstudio.bean.Car;
import org.springframework.beans.factory.FactoryBean;

/**
* FactoryBean工厂类
* 1. 编写FactoryBean的实现类
* 2. 在Spring配置文件中注册才有的功能
*/
public class CarFactoryBeanImpl implements FactoryBean<Car> {
/**
* 工厂方法:返回创建的对象
* @return
* @throws Exception
*/
@Override
public Car getObject() throws Exception {
Car car = new Car("工厂造车", 200);
return car;
}

/**
* 返回创建的对象的类型
* Spring会自动调用这个方法来确认创建的对象的类型
* @return
*/
@Override
public Class<?> getObjectType() {
return Car.class;
}

/**
* 是单例吗?
* false 不是单例
* true 是单例
* @return
*/
@Override
public boolean isSingleton() {
return false;
}
}

1
2
3
4
<!--配置一个工厂方法-->
<bean id="carFactoryBeanImpl"
class="com.runsstudio.factory.CarFactoryBeanImpl"></bean>

实现控制反转:

1
2
Object carFactoryBeanImpl = ioc.getBean("carFactoryBeanImpl");
System.out.println(carFactoryBeanImpl);

输出:Car{carName='工厂造车', price=200}

10 创建带有生命周期的Bean

  • 单实例Bean 容器启动的时候创建好,容器关闭的时候销毁
  • 多实例bean,获取的时候才创建

spring 可以为bean自定义一些声明周期方法,spring在创建和销毁的时候会调用指定的方法在XML中用

destroy-method

init-method 来指定

Bean生命周期:

构造器——》构造方法——》销毁

11 测试bean的后置处理器

Spring有一个接口:后置处理器,可以在Bean初始化前后处理方法

BeanPostProcessor

12 引用外部属性文件,管理数据库连接池

数据库连接池作为单实例是最好的,一个项目就一个连接池,连接池里管理很多链接

-------------文章已结束~感谢您的阅读-------------
穷且益坚,不堕青云之志。