Spring-Bean的配置

Spring-Bean的配置

配置Bean一共有三种方式

  1. 基于XML文件配置
  2. 基于注解配置
  3. 基于Java类配置

  不管是哪种配置,都是表达Bean定义的载体,其实本质都是为Spring容器提供Bean定义的信息。它们允许多项组合。

1.基于XML文件配置

下面基于XML配置文件定义了三个简单的Bean

1
2
3
4
5
6
7
8
<?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="cat" class="com.smart.model.Cat"/>
<bean id="dog" class="com.smart.model.Dog"/>
<bean id="people" class="com.smart.model.People"/>
</beans>

这段信息提供了实例化Cat、Dog、People这三个Bean的必需信息,IoC容器完全可以根据此创建这三个Bean的实例。

测试

1
2
3
4
5
6
7
8
9
10
11
public class test4 {
public static void main(String[] args) {
ApplicationContext ct=new ClassPathXmlApplicationContext("beans/beans.xml");
Cat c=ct.getBean("cat",Cat.class);
Dog d=ct.getBean("dog",Dog.class);
People p=ct.getBean("people",People.class);
if (c!=null&&d!=null&&p!=null){
System.out.println("IoC容器启动成功!!");
}
}
}

输出:

  配置文件中不允许出来id相同的Bean,但可以出现相同name的Bean,如果有多个相同name的Bean,则返回最后声明的Bean,因为后面声明的Bean将前面的覆盖了。


2.基于注解的配置

下面使用注解定义Bean

peopleBean

  声明一个id=people1的Bean,Spring通过@Autowired注解实现Bean的依赖注入,@Autowried的required属性表示当在容器里找不到匹配的Bean时也不会抛出异常(默认为true,找不到会抛出异常)。@Qualifier为指定注入Bean,如果容器有一个以上匹配的Bean,则可以通过@Qualifier注解限定Bean的名称。

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
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component("people1")
public class peopleBean {
private String name;
private catBean cat;

@Autowired
@Qualifier("dog1")
private dogBean dog;

public catBean getCat() {
return cat;
}

@Autowired(required = false)
public void setCat(catBean cat) {
this.cat = cat;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public dogBean getDog() {
return dog;
}

public void setDog(dogBean dog) {
this.dog = dog;
}
}

catBean

声明一个id=cat1的Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import org.springframework.stereotype.Component;

@Component("cat1")
public class catBean {
private String name;
private int age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

dogBean

声明一个id=dog1的Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import org.springframework.stereotype.Component;

@Component("dog1")
public class dogBean {
private String name;
private int age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

配置文件

  使用context命名空间,它提供了通过扫描类包以应用注解定义Bean的方式。通过context命名空间的component-scanbase-package的属性指定一个需要扫描的基类包。

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"//声明命名空间
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描com.smart.Beans 类包里定义的Bean-->
<context:component-scan base-package="com.smart.Beans"/>
</beans>

  如果仅希望扫描特定的类而并非基类包下的所有类,那么可以使用resource-pattern属性过滤出特定的类。如:

1
<context:component-scan base-package="com.smart" resource-pattern="Beans/*.class"/>

Spring仅会扫描基类包里Beans子包中的类。

测试类Test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import com.smart.Beans.peopleBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class test4 {
public static void main(String[] args) {
ApplicationContext ct=new ClassPathXmlApplicationContext("beans/component.xml");
peopleBean p=ct.getBean("people1",peopleBean.class);
if (p!=null&&p.getDog()!=null&&p.getCat()!=null){
System.out.println("IoC容器启动成功!!");
p.setName("老GS");
p.getCat().setName("小菊");
p.getDog().setName("旺财");
System.out.println(p.getName()+"的Cat叫"+p.getCat().getName()+",Dog叫"+p.getDog().getName());
}
}
}

结果:

  除了@Component以外,Spring提供了如下3个功能基本和@Component等效的注解,它们分别用于对DAO、Service、及Web层的Controller进行注解,所以也称这些注解为Bean的衍型注解。

  • @Repository: 用于对DAO实现类进行标注
  • @Service: 用于对Service实现类进行标注
  • @Controller: 用于对Controller实现类进行标注

提供这3个特殊的注解是为了让注解类本身的用途清晰化,此外Spring也赋予它们一些特殊的功能。


3.基于Java类的配置

  普通的POJO(简单Java对象)只要标注**@Configuration**注解,就可以为Spring容器提供Bean定义的信息了,每个标注了@Bean的类方法都相对于提供一个Bean的定义信息。

peopleConfig

  在PeopleConfig类定义处标注@Configuration注解,说明这个类可用于为Spring提供Bean的定义信息。类的方法处可以标注@Bean注解,Bean的类型由方法返回值类型决定,名称默认和方法名相同。由于@ Configuartion注解类本身已经标注了@Component注解,所以任何标注了@Configuration的类,它们可以像普通的Bean一样被注入其他的Bean中。如下面将AnimalConfig注入其中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(AnimalConfig.class)
public class PeopleConfig {

@Autowired
private AnimalConfig animalConfig;//像普通的Bean一样注入

@Bean
public People getPeople(){
People people=new People();
people.setC(animalConfig.peopleCat());
people.setD(animalConfig.peopleDog());
return people;
}
}

AnimalConfig

  定义AnimalConfig配置类。给第一个Bean命名为cat1。@Scope表示每次调用peopleDog都会返回一个新的Bean。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class AnimalConfig {
@Bean(name="cat1")
public Cat peopleCat(){
return new Cat();
}

@Scope("prototype")
@Bean
public Dog peopleDog(){
return new Dog();
}
}

通过@Configuration类启动IoC容器

  通过AnnotationConfigApplicationContext类的构造函数直接传入标注@Configuration的Java类,直接用该类中提供的Bean定义信息启动IoC容器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import com.smart.config.PeopleConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class test5 {
public static void main(String[] args) {
ApplicationContext ct= new AnnotationConfigApplicationContext(PeopleConfig.class);
People p=ct.getBean(People.class);
Cat c=ct.getBean("cat1",Cat.class);
Dog d=ct.getBean("peopleDog",Dog.class);
if (p!=null&&p.getD()!=null&&p.getC()!=null&&c!=null&&d!=null){
System.out.println("基于Java类配置Bean,IoC容器启动成功!!");
p.setName("老GS");
p.getC().setName("小菊");
p.getD().setName("旺财");
System.out.println(p.getName()+"的Cat叫"+p.getC().getName()+",Dog叫"+p.getD().getName());
}
}
}

  由于在PeopleConfig配置类中用@Import(AnimalConfig.class)将AnimalConfig配置类组装起来了,所以直接加载PeopleConfig.class就行了。如果没有组装需要如下操作:

1
2
3
4
5
6
AnnotationConfigApplicationContext ct= new AnnotationConfigApplicationContext();
//加载多个@Configuration配置类
ct.register(PeopleConfig.class);
ct.register(AnimalConfig.class);
//刷新容器以应用这些注册的配置类
ct.refresh();

结果:


通过XML配置文件引用@Configuration的配置
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--通过上下文扫描加载到PeopleConfig的配置类-->
<context:component-scan base-package="com.smart.config" resource-pattern="PeopleConfig"/>
</beans>

通过@Configuration配置类引用XML配置信息

  如下面xml中定义了三个Bean。

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.smart.model.Dog"/>
<bean class="com.smart.model.People"/>
<bean class="com.smart.model.Cat"/>
</beans>

  在@Configuration配置类中可通过@ImportResource引入XML配置文件,在配置类中即可直接通过@Autowired引用XML配置文件中定义的Bean。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@ImportResource("classpath:beans/beans.xml")//引入xml配置信息
public class PeopleConfig {

@Bean
@Autowired //注入xml里的Bean
public People getPeople1(Cat cat, Dog dog){
People people=new People();
people.setC(cat);
people.setD(dog);
return people;
}
}
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×