美文网首页
Spring学习笔记:Spring Bean的实例化

Spring学习笔记:Spring Bean的实例化

作者: 大力papa | 来源:发表于2021-01-08 18:09 被阅读0次

    本文仅供学习交流使用,侵权必删。
    不作商业用途,转载请注明出处

    Spring Bean的实例化有不同方式,本文将展示Spring Bean的各种实例化方式。

    构造器方式

    构造器方式实例化Bean只需在Bean的Class中定义构造器即可,然后将对应的Bean信息注册到容器中。
    以下例子通过Xml配置的方式展示

    • Bean的类定义
    public class User {
        private String name;
        private Integer age;
    
        public User() {
        }
    
        public User(String name) {
            this.name = name;
        }
    
        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 "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    • Xml配置信息
      <!--    构造器方法实例化bean配置-->
        <bean id="user-by-constructor" class="com.kgyam.domain.User"/>
    
    
    • 启动类
    public class BeanInstantiationDemo {
        public static void main(String[] args) {
            BeanFactory beanFactory = new ClassPathXmlApplicationContext ("classpath:META-INF/bean-instantiation-context.xml");
            User constructorUser = instantiationByConstructor (beanFactory);
    }
    
      static User instantiationByConstructor(BeanFactory beanFactory) {
            User user = beanFactory.getBean ("user-by-constructor", User.class);
            System.out.println ("instantiationByConstructor user:" + user);
            return user;
        }
    
    }
    

    静态工厂方法

    静态工厂方法就是在刚才的User类中添加一个静态工厂方法,然后将这个方法配置到Bean的配置信息factory-method

    • User中添加一个静态工厂方法
    public class User {
        private String name;
        private Integer age;
    
        public User() {
        }
    
        public User(String name) {
            this.name = name;
        }
    
        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 "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    
    
        public static User createUser() {
            return new User();
        }
    }
    
    • Xml配置信息
       <!--    静态工厂方法实例化bean配置-->
        <bean id="user-by-static-method" factory-method="createUser" class="com.kgyam.domain.User"/>
    
    
    • 启动类
    public class BeanInstantiationDemo {
        public static void main(String[] args) {
            BeanFactory beanFactory = new ClassPathXmlApplicationContext ("classpath:META-INF/bean-instantiation-context.xml");
                 User staticUser = instantiationByStaticMethod (beanFactory);
    }
    
    
      static User instantiationByStaticMethod(BeanFactory beanFactory) {
            User user = beanFactory.getBean ("user-by-static-method", User.class);
            System.out.println ("instantiationByStaticMethod user:" + user);
            return user;
        }
    
    }
    

    Factory Method

    工厂方法需要定义一个能创建User的工厂Bean,将这个工厂Bean配置到factory-bean

    • UserFactory接口
    public interface UserFactory {
        User createUser();
    }
    
    • UserFactory的默认实现
    /**
     * User实例工厂
     */
    public class DefaultUserFactory implements UserFactory {
        @Override
        public User createUser() {
            return User.createUser();
        }
    }
    
    • Xml配置
        <bean id="user-by-factory-method" factory-bean="user-factory" class="com.kgyam.domain.User"></bean>
    
        <!--    工厂方法的工厂bean配置-->
        <bean id="user-factory" class="com.kgyam.factory.DefaultUserFactory"/>
    
    • 启动类跟上面的是一样的,只是getBean的BeanName改下就好

    FactoryBean

    需要实现FactoryBean接口,并将实现类注册到容器中

    • FactoryBean的实现类
    /**
     * User的FactoryBean
     */
    public class UserFactoryBean implements FactoryBean {
        @Override
        public Object getObject() throws Exception {
            return new User ();
        }
    
        @Override
        public Class<?> getObjectType() {
            return User.class;
        }
    }
    
    • Xml配置
       <!--  通过factoryBean实例化user的factoryBean配置  -->
       <bean id="user-factory-bean" class="com.kgyam.domain.UserFactoryBean" />
    
    • 启动类这里,虽然bean定义的class是UserFactoryBean,但是接收返回的类型还是使用User,beanName改成对应Xml配置定义的。获取Bean的方法如下
    static User instantiationByFactroyBean(BeanFactory beanFactory) {
            User user = beanFactory.getBean ("user-factory-bean", User.class);
            System.out.println ("instantiationByFactroyBean user:" + user);
            return user;
        }
    

    ServiceLoaderFactoryBean

    通过ServiceLoaderFactoryBean的这种方式实例化Bean利用的是SPI机制实现的。

    • 接口类
    public interface UserService {
        User createUser();
    }
    
    
    • 接口实现类

    这里定义两个接口实现类

    public class DefaultUserServiceImpl implements UserService {
        @Override
        public User createUser() {
            User user = User.createUser();
            user.setName("defaultUser");
            return user;
        }
    }
    
    
    public class CustomUserServiceImpl implements UserService {
        @Override
        public User createUser() {
            User user = User.createUser();
            user.setName("customUser");
            return user;
        }
    }
    
    • META-INF下services配置
      这里注意的是配置文件名称需要时接口的限定类名,配置文件中配置的是实现类的限定类名。这里属于SPI的知识,不过多阐述
    com.kgyam.domain.service.DefaultUserServiceImpl
    com.kgyam.domain.service.CustomUserServiceImpl
    
    • Xml配置
      注意这里的class配置的是ServiceLoaderFactoryBean
        <bean id="service-loader-factory-bean"         class="org.springframework.beans.factory.serviceloader.ServiceLoaderFactoryBean">
            <property name="serviceType" value="com.kgyam.domain.service.UserService"/>
        </bean>
    
    • 启动类
    public class BeanInstantiationDemo {
       public static void main(String[] args) {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:META-INF/bean-instantiation-special-context.xml");
            instantiationByServiceLoader(applicationContext);
        }
    }
    
     /**
         * 通过ServiceLoaderFactoryBean方式实例化bean
         * <p>
         * 使用SPI的方式还是需要遵循SPI原来的规范,META-INF下设定好services的文件
         * 否则会无法找到这些实现类。
         *
         * @param beanFactory
         */
        static void instantiationByServiceLoader(BeanFactory beanFactory) {
            ServiceLoader<UserService> services = beanFactory.getBean("service-loader-factory-bean", ServiceLoader.class);
            Iterator<UserService> iterator = services.iterator();
            while (iterator.hasNext()) {
                User user = iterator.next().createUser();
                System.out.println(user);
            }
        }
    

    BeanDefinitionRegistry

    通过BeanDefinitionRegistry注册BeanDefinition实现Bean实例化

    • 启动类
      这里AnnotationConfigApplicationContext实现了BeanDefinitionRegistry,
      所以通过上下文对象注册即可。
    public class BeanInstantiationDemo {
       public static void main(String[] args) {
              AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext ();
            applicationContext.register (BeanInstantiationSpecialDemo.class);
    
            BeanDefinitionBuilder beanDefinitionBuilder = genericBeanDefinition (User.class);
            beanDefinitionBuilder.addPropertyValue ("name", "dali");
            /*
            因为AnnotationConfigApplicationContext实现了BeanDefinitionRegistry接口,所以可以直接调用
             */
            applicationContext.registerBeanDefinition ("dali-user", beanDefinitionBuilder.getBeanDefinition ());
            applicationContext.refresh ();
    
            User user = applicationContext.getBean ("dali-user", User.class);
            System.out.println ("BeanDefinitionRegistry#registerBeanDefinition(String,Object):" + user);
            applicationContext.close ();
        }
    }
    
    

    参考文献

    Spring官方文档

    相关文章

      网友评论

          本文标题:Spring学习笔记:Spring Bean的实例化

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