前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring 全家桶之 Spring Framework 5.3(二)- Part B

Spring 全家桶之 Spring Framework 5.3(二)- Part B

作者头像
RiemannHypothesis
发布2022-08-19 15:34:38
2340
发布2022-08-19 15:34:38
举报
文章被收录于专栏:Elixir

一、Spring IoC 容器 Bean 花式注册与获取

花式四:通过继承实现Bean的注册

在assign_value.xml中增加xml配置,继承其他bean的配置信息要使用parent属性

代码语言:javascript
复制
<!--继承用的配置信息-->
<bean id="stark10" class="com.citi.entity.Person">
    <property name="lastName" value="stark10"></property>
    <property name="age" value="18"></property>
    <property name="gender" value="男"></property>
    <property name="email" value="stark@stark-industry.com"></property>
</bean>

<!--继承stark10的配置信息-->
<bean id="stark11" class="com.citi.entity.Person" parent="stark10">
    <property name="lastName" value="stark11"></property>
</bean>

增加测试方法

代码语言:javascript
复制
@Test
public void testAssignByExtend(){
    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:assign_value.xml");

    Person stark11 = context.getBean("stark11",Person.class);
    Person stark10 = context.getBean("stark10",Person.class);

    System.out.println(stark10);
    System.out.println(stark11);
}

执行测试,除了名字不同,邮件性别等信息都是从stark10继承过来的

image.png
image.png

通过abstract属性将bean配置变成一个配置模版,只能用于继承配置信息,无法直接获取 修改xml配置,增加abstract=“true”

代码语言:javascript
复制
<bean id="stark10" class="com.citi.entity.Person" abstract="true">
    <property name="lastName" value="stark10"></property>
    <property name="age" value="18"></property>
    <property name="gender" value="男"></property>
    <property name="email" value="stark@stark-industry.com"></property>
</bean>

再次执行测试,获取stark10出错,stark01已被标记为abstarct,只能用于其他bean继承配置信息

image.png
image.png

花式五:实现互相依赖的Bean的注册

分别给Car,Book,Person实体类增加无参构造方法,并在其中打印一句话

代码语言:javascript
复制
System.out.println(this.getClass().getName() + "无参构造方法被调用");

新建一个bean的xml配置dependency_bean.xml

代码语言:javascript
复制
<?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:util="http://www.springframework.org/schema/util"
       xmlns:p = "http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-4.3.xsd">

    <bean id="person" class="com.citi.entity.Person"></bean>
    <bean id="car" class="com.citi.entity.Car"></bean>
    <bean id="book" class="com.citi.entity.Book"></bean>
</beans>

增加新的测试类及测试方法

代码语言:javascript
复制
@Test
public void testGetBean(){
    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:dependency_bean.xml");

    String[] beanDefinitionNames = context.getBeanDefinitionNames();
    for (String beanDefinitionName : beanDefinitionNames) {
        System.out.println(beanDefinitionName);
    }
}

Bean的创建顺序与xml中配置的顺序一致

image.png
image.png

想要改变顺序还可以使用depends-on标签

代码语言:javascript
复制
<bean id="person" class="com.citi.entity.Person" depends-on="car,book"></bean>
<bean id="car" class="com.citi.entity.Car"></bean>
<bean id="book" class="com.citi.entity.Book"></bean>

执行测试,实现了先创建依赖的car,book,最后再创建person

image.png
image.png

花式六:实现多实例Bean的注册

bean的注册默认是单实例的,创建多实例的Bean需要增加prototype属性

增加singleton_prototype_bean.xml配置文件

代码语言:javascript
复制
<?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:util="http://www.springframework.org/schema/util"
       xmlns:p = "http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-4.3.xsd">

    <bean id="person" class="com.citi.entity.Person"></bean>
    <bean id="car" class="com.citi.entity.Car"></bean>
    <bean id="book" class="com.citi.entity.Book"></bean>
</beans>

增加测试类及测试方法

代码语言:javascript
复制
public class SingletonPrototypeBeanTest {

    @Test
    public void testGetBean(){
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:singleton_prototype_bean.xml");

        System.out.println("IoC容器创建完成");
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }
}

执行测试方法,单实例bean在容器创建完成之前就已经创建了

image.png
image.png

将person增加scope属性,修改为多实例

代码语言:javascript
复制
<bean id="person" scope="prototype" class="com.citi.entity.Person"></bean>

修改测试代码

代码语言:javascript
复制
public class SingletonPrototypeBeanTest {

    @Test
    public void testGetBean(){
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:singleton_prototype_bean.xml");

        System.out.println("IoC容器创建完成");
        Person p1 = context.getBean(Person.class);
        Person p2 = context.getBean(Person.class);
        System.out.println(p1 == p2);

    }
}

执行测试,多实例Bean是在容器创建完成之后创建的,且多实例的Bean内存地址是不相同的

image.png
image.png

scope属性还有两个value是request和session,基本很少使用

花式七:Factory创建Bean

工厂分为静态工厂和实例工厂

  • 静态工厂: 工厂本身不用创建Bean,通过静态方法调用 对象 = 工厂类.工厂方法名
  • 实例工厂: 工厂本身需要创建Bean,通过先创建出一个工厂对象 工厂类 工厂对象 = new 工厂类(),从工厂对象获取实例 工厂对象.getBean() entity包中增加Tesla实体类
代码语言:javascript
复制
public class Tesla {

    private String name;
    private String battery; // 电池
    private String engine; // 电机
    private String chassis; //底盘
    private String bodywork; // 车身
    private String owner; // 车主
    // 此处省略getter/setter/toString方法
}    

新增facotry包,创建静态工厂和实例工厂类

代码语言:javascript
复制
```java
public class TeslaInstanceFactory {

    public Tesla getTesla(String owner){
        System.out.println("TeslaInstanceFactory被调用");
        Tesla tesla = new Tesla();
        tesla.setName("Model 3");
        tesla.setBattery("4680");
        tesla.setOwner(owner);

        return tesla;
    }
}

代码语言:javascript
复制
public class TeslaStaticFactory {

    public static Tesla getTesla(String owner){
        System.out.println("TeslaStaticFactory被调用");
        Tesla tesla = new Tesla();
        tesla.setName("Model3");
        tesla.setBattery("4680");
        tesla.setOwner(owner);

        return tesla;
    }
}
静态工厂创建 Bean

在factory.xml中创建静态工厂的配置信息

代码语言:javascript
复制
<?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:util="http://www.springframework.org/schema/util"
       xmlns:p = "http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-4.3.xsd">

    <!--静态工厂创建bean,不需要创建工厂本身
        id:指的是Bean的id,不是工厂的id
        class:值得是静态工厂类的全类名
        factory-method:指定哪个方法创建Tesla Bean
        constructor-arg: 使用setter方法赋值
    -->
    <bean id="model3" class="com.citi.factory.TeslaStaticFactory" factory-method="getTesla">
        <!--相当于工厂方法getTesla传入的参数,不加这个属性会报错-->
        <constructor-arg value="musk1"></constructor-arg>
    </bean>
    
</beans>    

创建测试类FactoryTest,新增测试方法testGetBeanByStaticFactory()

代码语言:javascript
复制
public class FactoryTest {

    @Test
    public void testGetBeanByStaticFactory(){
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:factory.xml");

        System.out.println("IoC容器创建完成");

        Tesla model3 = context.getBean("model3",Tesla.class);
        System.out.println(model3);
    }
    
}    

执行测试方法,控制台输出如下,Tesla Bean创建成功

image.png
image.png
实例工厂创建 Bean

在factory.xml中增加实例工厂创建Bean的配置

代码语言:javascript
复制
<bean id="ShanghaiGigaFactory" class="com.citi.factory.TeslaInstanceFactory" >
</bean>

<bean id="modelS" class="com.citi.entity.Tesla" factory-bean="ShanghaiGigaFactory" factory-method="getTesla">
    <!--相当于工厂方法getTesla传入的参数,不加这个属性会报错-->
    <constructor-arg value="musk2"></constructor-arg>
</bean>

增加测试方法

代码语言:javascript
复制
@Test
public void testGetBeanByInstanceFactory(){
    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:factory.xml");

    System.out.println("IoC容器创建完成");

    String[] beanDefinitionNames = context.getBeanDefinitionNames();
    for (String beanDefinitionName : beanDefinitionNames) {
        System.out.println(beanDefinitionName);
    }

    Tesla modelS = context.getBean("modelS",Tesla.class);
    System.out.println(modelS);
}

控制台成功打印出modelS

image.png
image.png
实现FactoryBean接口创建 Bean

新增一个FactorBean的实现类BerlinGigaFactoryBean,泛型为要创建的类型

代码语言:javascript
复制
public class BerlinGigaFactoryBean implements FactoryBean<Tesla> {

    // 返回创建的对象
    @Override
    public Tesla getObject() throws Exception {
        System.out.println("实现FactoryBean接口创建Bean");
        Tesla tesla = new Tesla();
        tesla.setName("Cybertruck");
        return tesla;
    }

    // 返回常见的类型
    @Override
    public Class<?> getObjectType() {
        return Tesla.class;
    }

    // 是否为单例,默认非单例模式
    @Override
    public boolean isSingleton() {
        return false;
    }
}

在factory.xml中增加配置

代码语言:javascript
复制
<!--实现FactoryBean接口创建Bean配置文件-->
<bean id="BerlinGigaFactory" class="com.citi.factory.BerlinGigaFactoryBean">

</bean>

增加测试方法

代码语言:javascript
复制
@Test
public void testGetBeanByImplFactoryBean() throws Exception {
    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:factory.xml");

    System.out.println("IoC容器创建完成");

    String[] beanDefinitionNames = context.getBeanDefinitionNames();
    for (String beanDefinitionName : beanDefinitionNames) {
        System.out.println(beanDefinitionName);
    }

    Tesla cybertruck = (Tesla) context.getBean("berlinGigaFactory");
    System.out.println(cybertruck);
}

执行测试方法,直接获取实现FactoryBean接口的实例即可得到Tesla Bean cybertruck

image.png
image.png

实现FactoryBean接口创建Bean,在容器中都是获取Bean时才创建Bean,跟方法中是否是单例无关 plus:BeanFactory和FactoryBean有什么区别?

BeanFactory是容器的顶层接口,ApplicationContext就是间接实现了该接口,可以通过getBean()方法获取容器中的Bean,FactoryBean接口是用来注册Bean的,使用该接口需要实现接口中的方法。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-01-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Spring IoC 容器 Bean 花式注册与获取
    • 花式四:通过继承实现Bean的注册
      • 花式五:实现互相依赖的Bean的注册
        • 花式六:实现多实例Bean的注册
          • 花式七:Factory创建Bean
            • 静态工厂创建 Bean
            • 实例工厂创建 Bean
            • 实现FactoryBean接口创建 Bean
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档