美文网首页【每天学点Spring】
【每天学点Spring】FactoryBean

【每天学点Spring】FactoryBean

作者: 伊丽莎白2015 | 来源:发表于2022-04-30 21:59 被阅读0次

    关于FactoryBean的介绍:
    Factory-Bean,工厂-造出Bean,首先它是一个Spring重要的接口,有很多实现类如:ProxyFactoryBean,JndiObjectFactoryBean等。

    1. FactoryBean方法

    • T getObject(): 返回FactoryBean创建的对象,创建的对象会被spring容器管理。
    • Class<?> getObjectType(): 返回FactoryBean创建Bean的类型。
    • default boolean isSingleton(): 定义getObject()创建的对象是否为单例。

    2. 简单例子

    2.1 实现FactoryBean接口:
    @Data
    @AllArgsConstructor
    public class User {
        private int id;
    }
    

    UserFactory类实现了FactoryBean接口,在getObject()里负责创建新的user对象

    @Data
    public class UserFactory implements FactoryBean<User> {
        private int factoryId;
        private int userId;
    
        @Override
        public User getObject() throws Exception {
            return new User(userId);
        }
    
        @Override
        public Class<?> getObjectType() {
            return User.class;
        }
    
        @Override
        public boolean isSingleton() {
            return false;
        }
    }
    
    2.2 使用@Configuration配置bean:

    定义了一个Bean,返回UserFactory。
    这里比较我有意思的是,如果UserFactory是普通的bean,那么名称为user的bean就是UserFactory的实例。
    但恰恰因为UserFactory不是普通的bean(它实现了FactoryBean接口),所以并不能像普通bean那样的用法,而是会调用getObject()方法,来创建出新的对象实例。
    以下的@Configuration会创建出两个bean:

    • bean, name = "user", 实例是user对象。
    • bean,name="&user", 实例是userFactory对象。
    @Configuration
    public class FactoryBeanAppConfig {
        @Bean(name = "user")
        public UserFactory userFactory() {
            UserFactory factory = new UserFactory();
            factory.setFactoryId(1001);
            factory.setUserId(1);
            return factory;
        }
    }
    

    测试类:

    @SpringBootTest
    public class FactoryBeanAppConfigTest {
        @Autowired
        private User user;
    
        @Resource(name = "&user")
        private UserFactory userFactory;
    
        @Test
        public void test() {
            assertThat(user.getId(), equalTo(1));
            assertThat(userFactory.getFactoryId(), equalTo(1001));
        }
    }
    

    3. AbstractFactoryBean

    Spring提供了AbstractFactoryBean抽象类,它是FactoryBean的一个实现,我们可以通过继承它更方便的创建出实例。

    3.1 AbstractFactoryBean的singleton属性

    AbstractFactoryBean类有个参数:singleton,默认为true,也就是默认通过getObject()创建出的对象都是单例的。如果设为false,则会调用createInstance()方法来创建实例(该方法是抽象方法,需要子类实现)。
    以下是AbstractFactoryBean类getObject()方法源码(基于版本:spring-beans:5.3.13.jar),可以看出上述逻辑:

    public final T getObject() throws Exception {
        if (isSingleton()) {
            return (this.initialized ? this.singletonInstance : getEarlySingletonInstance());
        } else {
            return createInstance();
        }
    }
    
    3.2 AbstractFactoryBean例子

    新建两个AbstractFactoryBean的子类:

    • SingleToolFactory:继续了AbstractFactoryBean,默认singleton为true。
    • NonSingleToolFactory:set singleton为false。
    @Data
    public class SingleUserFactory extends AbstractFactoryBean<User> {
        private int factoryId;
        private int userId;
    
        @Override
        public Class<?> getObjectType() {
            return User.class;
        }
    
        @Override
        protected User createInstance() throws Exception {
            return new User(userId);
        }
    }
    
    @Data
    public class NonSingleUserFactory extends AbstractFactoryBean<User> {
        private int factoryId;
        private int userId;
    
        public NonSingleUserFactory() {
            setSingleton(false);
        }
    
        @Override
        public Class<?> getObjectType() {
            return User.class;
        }
    
        @Override
        protected User createInstance() throws Exception {
            return new User(userId);
        }
    }
    

    用@Configuration配置bean:

    @Configuration
    public class AbstractFactoryBeanConfig {
        @Bean(name = "singleUser")
        public SingleUserFactory singleUserFactory() {
            SingleUserFactory factory = new SingleUserFactory();
            factory.setFactoryId(3001);
            factory.setUserId(1);
            return factory;
        }
    
        @Bean(name = "nonSingleUser")
        public NonSingleUserFactory nonSingleUserFactory() {
            NonSingleUserFactory factory = new NonSingleUserFactory();
            factory.setFactoryId(3002);
            factory.setUserId(2);
            return factory;
        }
    }
    

    测试,可以看出单例FactoryBean创建的两个user对象实例是一样的。
    非单例的FactoryBean创建的两个user对象实例是不一样的。

    @SpringBootTest
    public class AbstractFactoryBeanTest {
    
        @Resource(name = "singleUser")
        private User user1;
    
        @Resource(name = "singleUser")
        private User user2;
    
        @Resource(name = "nonSingleUser")
        private User user3;
    
        @Resource(name = "nonSingleUser")
        private User user4;
    
        @Test
        public void testSingleUserFactory() {
            assertThat(user1.getId(), equalTo(1));
            assertTrue(user1 == user2);
        }
    
        @Test
        public void testNonSingleUserFactory() {
            assertThat(user3.getId(), equalTo(2));
            assertThat(user4.getId(), equalTo(2));
            assertTrue(user3 != user4);
        }
    }
    

    参考:
    baeldung - How to use the Spring FactoryBean?

    相关文章

      网友评论

        本文标题:【每天学点Spring】FactoryBean

        本文链接:https://www.haomeiwen.com/subject/ytasyrtx.html