Java基础Spring

[Spring]Bean与BeanDefinition

2020-11-28  本文已影响0人  AbstractCulture

IOC容器

IOC容器主要的职责有:

Spring官网对容器的概述图,业务Java对象加上元数据的配置,被Spring IOC进行读取、解析、注册到IOC容器后,对外界提供使用。

IOC

Bean

  1. PersonFactory
@Component
public class PersonFactory {

    /**
     * 这个Bean即可以为personC,也可以为Kobe
     */
    @Bean({"personC", "Kobe"})
    public Person getPerson() {
        return new Person("I am Kobe who created by PersonFactory");
    }
}
  1. Demo
@Configuration
@ComponentScan(value = "com.xjm")
public class BeanDefinitionDemoByAnnotation {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationContextDemo.class);
        Person kobe = (Person) applicationContext.getBean("Kobe");
        System.out.println(kobe.toString());
    }
}

BeanDefinition

根据配置,用来描述Bean的BeanDefinition,它是一个接口,主要定义了一些Bean该有的方法,让下层实现类去实现这些功能,以下声明的属性均不在BeanDefinition中,只是便于理解,实际上Beandefinition只是定义了它们的getter和setter:

Bean的作用域

Bean的作用域 ,可以指定值为:singletonprototyperequestsessionapplication

范围 描述
singleton 默认的作用域,单例
prototype 原型模式,也就是可以创建多个对象实例
request 生命周期为一个Http请求的Bean。即每个Http请求都会产生一个自己的Bean实例。仅在ApplicationContext中有效
session 生命周期为整个Http的Bean。仅在ApplicationContext中有效
application 作用域限定为ServletContext的生命周期

我们从xml或者注解中定义的内容都会被解析成BeanDefinition,再根据BeanDefinition产生Bean实例,这就跟Person.java->Person.class->Person是类似的。

实例化对象的几种方式

<?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">
    <!--1. 使用类的无参构造函数创建-->
    <bean id="personA" class="com.xjm.model.Person" scope="singleton" lazy-init="true" primary="true"></bean>
    <!--2. 通过静态工厂进行创建-->
    <bean id="personB" class="com.xjm.model.PersonStaticFactory" factory-method="getPerson" scope="singleton"></bean>
    <!--3. 使用实例工厂进行创建-->
    <bean id="personFactory" class="com.xjm.model.PersonFactory"></bean>
    <bean id="personC" factory-bean="personFactory" factory-method="getPerson" scope="singleton"></bean>
</beans>
public class Person {

    private String name;

    private Integer age;

    public Person(String name) {
        this.name = name;
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class PersonFactory {

    public Person getPerson() {
        return new Person("I am Kobe who created by PeronFactory");
    }
}
public class PersonStaticFactory {

    public static Person getPerson() {
        return new Person("I am James who created by PersonStaticFactory");
    }
}
@SuppressWarnings("all")
public class BeanDefinitionDemo {
    public static void main(String[] args) {
        // 1. 声明配置类路径
        String xmlPath = "D:\\Spring\\spring-framework-5.1.x\\spring-demo\\src\\main\\resources\\spring\\spring-config.xml";
        // 2. 加载xml配置类
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext(xmlPath);
        System.out.println("****************Before Spring********************");
        // 默认的构造函数
        Person person = new Person();
        System.out.println(person.toString());
        // 使用静态方法创建Person
        Person kobe = PersonStaticFactory.getPerson();
        System.out.println(kobe.toString());
        // 使用工厂创建Person
        PersonFactory personFactory = new PersonFactory();
        System.out.println(personFactory.getPerson().toString());
        System.out.println("****************Using Spring********************");
        // 默认构造函数创建Bean
        Person personA = (Person) applicationContext.getBean("personA");
        // 通过静态工厂方法创建Bean
        Person personB = (Person) applicationContext.getBean("personB");
        // 通过工厂方法创建Bean
        Person personC = (Person) applicationContext.getBean("personC");
        System.out.println(personA.toString()+"hashcode:"+personA.hashCode());
        System.out.println(personB.toString()+"hashcode:"+personB.hashCode());
        System.out.println(personC.toString()+"hashcode:"+personC.hashCode());
        System.out.println("************Singleton*********************");
        Person personAA = (Person) applicationContext.getBean("personA");
        Person personBB = (Person) applicationContext.getBean("personB");
        Person personCC = (Person) applicationContext.getBean("personC");
        System.out.println(personAA.toString()+"hashcode:"+personAA.hashCode());
        System.out.println(personBB.toString()+"hashcode:"+personBB.hashCode());
        System.out.println(personCC.toString()+"hashcode:"+personCC.hashCode());
    }
}

可以看到,在xml配置好对应的初始化方式后,Spring就会根据配置的方式对对象实例进行初始化。

demo

AbstractBeanDefinition

AbstractBeanDefinition是BeanDefinition接口的抽象实现,也就是说它负责定义下层子类可以复用的代码,提供一些公共参数。

以下是AbstractBeanDefinition中定义的一些属性

BeanDefinition XML
scope <bean scope="xxx" />
lazyInit <bean lazy-init="true" />
beanClass <bean class="xxx" />
autowireCandidate <bean autowire-candidate="true" />
primary <bean primary="true" />
factoryMethodName <bean factory-method="getPerson"> 单独使用getPerson需要为static
factoryBeanName <bean id="personFactory" class="com.xjm.model.PersonFactory"></bean>
<bean id="personC" factory-bean="personFactory" factory-method="getPerson">
可以理解为先创建personFactory,实现FactoryBean的接口,然后根据getObject再调用里面的getPerson方法

BeanDefinition的UML图

UML

OK,我们看到AbstractBeanDefinition是在Beandefinition上做了一些简单的属性声明与构造器,具体的实现还是由GenericBeanDefinition、RootBeanDefinition、ChildBeanDefinition去实现的,那么这三者之间有什么联系呢?下章见分晓

总结

上一篇下一篇

猜你喜欢

热点阅读