【Spring温故】4.Bean之间的关系和作用域

一、Spring Bean之间关系:

1、继承:

(1)、Spring Bean的继承关系为配置继承,它是在bean配置文件中使用bean的parent属性指定要继承的具体bean id;
拿上篇文章的实例来做讲解,首先新建一个spring xml配置文件,并新建两个同样的address 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="address1" class="com.monkey.yb.autowire.Address">
        <property name="city" value="HangZhou"></property>
        <property name="street" value="xihu"></property>
    </bean>

    <bean id="address2" class="com.monkey.yb.autowire.Address">
        <property name="city" value="HangZhou"></property>
        <property name="street" value="binjiang"></property>
    </bean>
</beans>

按正常的逻辑,再新建一个Main方法,并调用上述两个bean id,检查输出结果:

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans-release.xml");
        Address address1 = (Address) context.getBean("address1");
        System.out.println(address1);

        Address address2 = (Address) context.getBean("address2");
        System.out.println(address2);
    }
}
Address{city='HangZhou', street='xihu'}
Address{city='HangZhou', street='binjiang'}

从上述内容可以看出,两个address都有很多相同的参数配置,如class、property city 和property street,但实际在开发中为避免重复造轮子的出现,这样写是会有问题的(若一个配置bean修改,则全部都需要修改),spring为了规避这种重复造轮子的现象给我们提供了bean配置继承的一个属性“parent”,如我们可以将上述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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="address1" class="com.monkey.yb.autowire.Address">
        <property name="city" value="HangZhou"></property>
        <property name="street" value="xihu"></property>
    </bean>

    <bean id="address2" parent="address1"></bean>
</beans>

不对main方法进行任何修改,直接运行,我们将得到以下结果:

Address{city='HangZhou', street='xihu'}
Address{city='HangZhou', street='xihu'}

从上述栗子可以看出,使用parent属性后,address2输出的内容和address1是一模一样的,即address2其实是继承了address1的所有属性配置。

(2)、子bean从父bean中继承配置,包括bean的属性配置;
(3)、子bean可以覆盖从父bean中继承过来的属性配置,比如覆盖street属性配置;

在实际中,完全继承的用法并不多,但继承后覆盖原配置属性的情况还是有的,比如我们要继承address1,并覆盖street的配置,则我们可以在配置文件中再次指定street的property属性即可,如:

<?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="address1" class="com.monkey.yb.autowire.Address">
        <property name="city" value="HangZhou"></property>
        <property name="street" value="xihu"></property>
    </bean>

    <bean id="address2" parent="address1"></bean>

    <bean id="address3" parent="address1">
        <property name="street" value="xiaoshan"></property>
    </bean>
    
</beans>

在main方法中新增address3调用方法,并查看结果:

package com.monkey.yb.release;

import com.monkey.yb.autowire.Address;
import com.monkey.yb.autowire.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans-release.xml");
        Address address1 = (Address) context.getBean("address1");
        System.out.println(address1);

        Address address2 = (Address) context.getBean("address2");
        System.out.println(address2);

        /**
         * address继承了address1,同时把address1的street值覆盖为"xiaoshan"
         */
        Address address3 = (Address) context.getBean("address3");
        System.out.println(address3);

    }
}

输出结果如下:

Address{city='HangZhou', street='xiaoshan'}
(4)、bean的abstract属性设置为true时,这样的bean不能被ioc容器实例化,只用来被继承配置;
(5)、可以忽略父bean的class属性,让子bean指定自己的类,而共享相同的配置属性,但此时abstract必须设为true。
<?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="address1" class="com.monkey.yb.autowire.Address">
        <property name="city" value="HangZhou"></property>
        <property name="street" value="xihu"></property>
    </bean>

    <bean id="address2" parent="address1"></bean>

    <bean id="address3" parent="address1">
        <property name="street" value="xiaoshan"></property>
    </bean>
    
    <bean id="address4" parent="address1" abstract="true">
        <property name="street" value="xiaoshan"></property>
    </bean>

</beans>

在main方法中再新增address4的调用方法,如:

package com.monkey.yb.release;

import com.monkey.yb.autowire.Address;
import com.monkey.yb.autowire.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans-release.xml");
        Address address1 = (Address) context.getBean("address1");
        System.out.println(address1);

        Address address2 = (Address) context.getBean("address2");
        System.out.println(address2);

        /**
         * address继承了address1,同时把address1的street值覆盖为"xiaoshan"
         */
        Address address3 = (Address) context.getBean("address3");
        System.out.println(address3);


		Address address4 = (Address) context.getBean("address4");
		System.out.println(address4);

    }
}

再次运行时则会返回以下异常(因为address4 声明了abstract属性值为true,所以调用时返回异常):

Exception in thread "main" org.springframework.beans.factory.BeanIsAbstractException: Error creating bean with name 'address4': Bean definition is abstract
at org.springframework.beans.factory.support.AbstractBeanFactory.checkMergedBeanDefinition(AbstractBeanFactory.java:1332)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:285)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1082)
at com.monkey.yb.release.Main.main(Main.java:23)

2、依赖:

Spring允许用户通过depends-on属性来设定bean的前置依赖bean,前置依赖的bean会在本bean实例化之前创建好;
如果前置依赖多个bean,则可以通过逗号、空格等方式来配置多个bean的名称。

二、Spring Bean的作用域:

发布了168 篇原创文章 · 获赞 0 · 访问量 7819

猜你喜欢

转载自blog.csdn.net/weixin_42661815/article/details/102407722
今日推荐