Spring的艺术(三):关于Spring中的Bean,一文搞定

579 阅读3分钟

听说微信搜索《Java鱼仔》会变更强哦!

本文收录于JavaStarter ,里面有我完整的Java系列文章,学习或面试都可以看看哦

本章的内容基于官方文档编写: docs.spring.io/spring-fram…

Spring版本为5.2.9

(一)Bean的作用域

Spring中Bean的作用域一共有六种

在这里插入图片描述

(1.1)singleton单例作用域

spring中的bean默认使用单例作用域,即全局只创建这一个bean对象,在程序中获取到的bean都是同一个。当然也可以显式的配置作用域:

<bean id="user" class="com.javayz.pojo.User" scope="singleton">

(1.2)prototype原型作用域

原型模式是指每次从容器中get一个Bean对象的时候都会产生一个新对象

<bean id="user" class="com.javayz.pojo.User" scope="prototype">

(1.3)web开发中使用的另外四种作用域

request、session、application和websocket只能在web开发中使用,分别表示:

request:bean在一个请求中共用一个。

session:bean在同一个session中共用一个。

application:bean在单个ServletContext中共用一个。

websocket:bean在单个Websocket中共用一个。

(二)Bean的自动装配

在之前的内容中,所有的bean都是手动去给其赋值,除了手动赋值外,Bean还支持隐式地自动装配

首先搭建一个简单的例子用于测试:

2.1、例子搭建

两个实体类:

public class Teacher {
    public void teach(){
        System.out.println("上课");
    }
}
public class Student {
    private String name;
    private Teacher teacher;
    //省略get、set方法
}

bean.xml

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="teacher" class="com.javayz.pojo.Teacher"/>
    <bean id="student" class="com.javayz.pojo.Student">
        <property name="name" value="javayz"/>
        <property name="teacher" ref="teacher"/>
    </bean>
</beans>

测试:

@org.junit.Test
public void test(){
    ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
    Student student = (Student) context.getBean("student");
    student.getTeacher().teach();
}

这是一种手动装配的方式,在bean.xml中,我们给teacher这个变量手动装配了teacher这个id的bean。现在我们使用自动装配:

2.2 autowire自动装配

<bean id="teacher" class="com.javayz.pojo.Teacher"/>
<bean id="student" class="com.javayz.pojo.Student" autowire="byName">
    <property name="name" value="javayz"/>
</bean>

在这里我们没有写teacher属性对应哪个bean,而是用了autowire="byName",Spring容器就会自动帮我们根据bean的名称去寻找对应的bean。除了byName后,还有其他的几种方式:

byName:自动在上下文中查找,找到和自己set方法后的值名称相同的bean;

byType:自动在上下文中查找,找到和自己对象类型相同的bean,使用byType需要保证bean全局唯一;

(三) 使用注解实现自动装配

使用注解需要我们配置开启:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

</beans>

还是上面的这个例子,这次在xml文件中只申明一个bean:

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>
    <bean id="teacher" class="com.javayz.pojo.Teacher"/>
    <bean id="student" class="com.javayz.pojo.Student"/>
</beans>

在实体类中通过@Autowired注解注入Bean

public class Student {
    private String name;
    @Autowired
    private Teacher teacher;
    //省略get、set方法
}

最终实现的效果和手动的注入是一样的。如果你在xml中为同一个类定义了多个bean,则可以使用@Qualifier()指定某个bean:

public class Student {
    private String name;
    @Autowired
    @Qualifier(value = "teacher2")
    private Teacher teacher;
}

除了使用@Autowired外,还可以使用@Resocure注解装配bean

public class Student {
    private String name;
    @Resource
    private Teacher teacher;
}

@Autowired和@Resource的区别在于:

@Autowired通过ByName方式实现,如果找不到对象就报空指针异常;

@Resource通过Byname方式实现,如果找不到名字,就通过ByType实现,否则就报错;