jieye の 数字花园

Search

Search IconIcon to open search

Spring bean相关

Last updated Unknown

想到写加瓦也有几个月了,但是一直对 spring 的想到写加瓦也有几个月了,但是一直对 spring 的机制都不是很了解,如果是在现成的代码上修改,那不了解也没关系,现在要自己独立完成很多新模块的建立,所以借这个机会学习下

首先,定义 bean 和注入 bean 是不同的概念

# 定义 bean

现有学生和老师类 balabala

  1. xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?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="student" class="test.Student">
        <property name="name" value="张三"/>
        <property name="teacher" ref="teacher"/>
    </bean>
 
    <bean id="teacher" class="test.Teacher">
        <property name="name" value="李四"/>
    </bean>
 
</beans>
  1. 基于注解
    Spring 为提供了四个注解,这些注解的作用与上面的 XML 定义 bean 效果一致,在于将组件交给 Spring 容器管理。组件的名称默认是类名(首字母变小写),也可以自己修改:
    @Component:当对组件的层次难以定位的时候使用这个注解
    @Controller:表示控制层的组件
    @Service:表示业务逻辑层的组件
    @Repository:表示数据访问层的组件
    使用这些注解的时候还有一个地方需要注意,就是需要在 applicationContext.xml 中声明 contex:component-scan…一项,指明 Spring 容器扫描组件的包目录。
    详见注解
1
2
3
@Component("teacher")
public class Teacher {
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?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">
 
    <!--扫描组件的包目录-->
    <context:component-scan base-package="test"/>
 
</beans>
  1. 基于 java 类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@Configuration
public class BeansConfiguration {
 
    @Bean
    public Student student(){
        Student student=new Student();
        student.setName("张三");
        student.setTeacher(teacher());
        return student;
    }
 
    @Bean
    public Teacher teacher(){
        Teacher teacher=new Teacher();
        teacher.setName("李四");
        return teacher;
    }
 
}

上面三种方法只是定义了 bean,注入仍然是手动的

# 自动注入

Spring 提供了五种自动装配的类型
no:顾名思义, 显式指明不使用Spring的自动装配功能
byName:根据属性和组件的名称匹配关系来实现bean的自动装配
byType:根据属性和组件的类型匹配关系来实现bean的自动装配,有多个适合类型的对象时装配失败
constructor:与byType类似是根据类型进行自动装配,但是要求待装配的bean有相应的构造函数
autodetect:利用Spring的自省机制判断使用byType或是constructor装配

  1. xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?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="student" class="test.Student" autowire="byName">
        <property name="name" value="张三"/>
    </bean>
 
    <bean id="teacher" class="test.Teacher">
        <property name="name" value="李四"/>
    </bean>
 
</beans>

这里并没有像上面一样显式为 Student 对象注入 Teacher 属性,而是使用 autowired=“byName"代替,这样一来 Spring 会帮我们处理这些细节,将名字是 teacher 的组件注入到 Student 对象中。
2. 基于注解的自动装配

@Resource 和@Autowired 的区别。@Resource 默认是使用 byName 进行装配,@Autowired 默认使用 byType 进行装配。详见注解

 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
@Component("teacher")
public class Teacher {
 
    @Value("李四")
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}
@Component("student")
public class Student {
 
    @Value("张三")
    private String name;
 
    @Resource
    private Teacher teacher;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Teacher getTeacher() {
        return teacher;
    }
 
    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }
}

# 日常使用总结

对于半路出家的我来说,刚开始一点都不懂 xml 配置,只能理解一点点基于注解的 bean 定义。
优点

  1. 可以摆脱使用 XML 或是 Java 类对大量 bean 进行配置的噩梦,让程序变得简洁。
  2. 可以清楚地指明组件所在的层次

缺点
但是也有特殊的情况,比如说配置数据源,也许某个组件并不是你写的(来自于 Spring 或是第三方 jar 包里面的组件等),没有办法在这些组件里面加上这些注解使之成为 Spring 容器管理的 bean(别人也不会为你加上这些注解,因为他们不知道你会使用到哪些组件)。这种情况下就得使用 XML 或是 Java 类进行配置了。这也是我在阿里的项目中遇到的情况。