zoukankan      html  css  js  c++  java
  • Spring实例化Bean的三种方式

    官网阐述:

    在Spring5核心的1.3.2章节

    实例化Bean

    bean定义本质上是用于创建一个或多个对象的配方。容器在被询问时查看命名bean的配方,并使用由该bean定义封装的配置元数据来创建(或获取)实际对象。

    如果使用基于XML的配置元数据,则指定要在 <bean/> 元素的 class 属性中实例化的对象的类型(或类)。此 class 属性(内部是 BeanDefinition 实例上的 Class 属性)通常是必需的。 您可以通过以下两种方式之一使用 Class 属性:

    • 通常,在容器本身通过反向调用其构造函数直接创建bean的情况下指定要构造的bean类,稍微等同于使用 new 运算符的Java代码。

    • 要指定包含为创建对象而调用的 static 工厂方法的实际类,在不常见的情况下,容器在类上调用 static 工厂方法来创建bean。从 static 工厂方法的调用返回的对象类型可以完全是同一个类或另一个类。

    内部类名

    如果要为 static 嵌套类配置bean定义,则必须使用嵌套类的二进制名称。

    例如,如果 com.example 包中有一个名为 SomeThing 的类,并且此 SomeThing 类具有名为 OtherThingstatic 嵌套类,则bean定义中 class 属性的值将为 com.example.SomeThing$OtherThing

    请注意,在名称中使用 $ 字符可以将嵌套类名与外部类名分开。

    使用构造函数实例化

    当您通过构造方法创建bean时,所有普通类都可以使用并与Spring兼容。也就是说,正在开发的类不需要实现任何特定接口或以特定方式编码。简单地指定bean类就足够了。但是,根据您为该特定bean使用的IoC类型,您可能需要一个默认(空)构造函数。

    Spring IoC容器几乎可以管理您希望它管理的任何类。它不仅限于管理真正的JavaBeans。大多数Spring用户更喜欢实际的JavaBeans,只有一个默认(无参数)构造函数,并且在容器中的属性之后建模了适当的setter和getter。您还可以在容器中拥有更多异国情调的非bean样式类。例如,如果您需要使用绝对不符合JavaBean规范的旧连接池,那么Spring也可以对其进行管理。

    使用基于XML的配置元数据,您可以按如下方式指定bean类:

    <bean id="exampleBean" class="examples.ExampleBean"/>
    <bean name="anotherExample"class="examples.ExampleBeanTwo"/>
    使用静态工厂方法实例化

    定义使用静态工厂方法创建的bean时,请使用 class 属性指定包含 static 工厂方法的类和名为 factory-method 的属性,以指定工厂方法本身的名称。您应该能够调用此方法(使用可选参数,如稍后所述)并返回一个活动对象,随后将其视为通过构造函数创建的对象。这种bean定义的一个用途是在遗留代码中调用 static 工厂。

    以下bean定义指定通过调用工厂方法来创建bean。该定义未指定返回对象的类型(类),仅指定包含工厂方法的类。在此示例中, createInstance() 方法必须是静态方法。以下示例显示如何指定工厂方法:

    <bean id="clientService"
        class="examples.ClientService"
        factory-method="createInstance"/>

    以下示例显示了一个可以使用前面的bean定义的类:

    public class ClientService {
        private static ClientService clientService = new ClientService();
        private ClientService() {}
    ​
        public static ClientService createInstance() {
            return clientService;
        }
    }
    使用实例工厂方法实例化

    与通过 static factory method 进行实例化类似,使用实例工厂方法进行实例化会调用非静态方法从容器中创建一个新bean的现有bean。要使用此机制,请将class 属性保留为空,并在 factory-bean 属性中指定当前(或父级或祖先)容器中bean的名称,该容器包含要调用以创建对象的实例方法。使用 factory-method 属性设置工厂方法本身的名称。以下示例显示如何配置此类bean:

    <!-- the factory bean, which contains a method called createInstance() -->
    <bean id="serviceLocator" class="examples.DefaultServiceLocator">
        <!-- inject any dependencies required by this locator bean -->
    </bean><!-- the bean to be created via the factory bean -->
    <bean id="clientService"
        factory-bean="serviceLocator"
        factory-method="createClientServiceInstance"/>

    以下示例显示了相应的Java类:

    public class DefaultServiceLocator {
    ​
        private static ClientService clientService = new ClientServiceImpl();
    ​
        public ClientService createClientServiceInstance() {
            return clientService;
        }
    }

    一个工厂类也可以包含多个工厂方法,如以下示例所示:

    <bean id="serviceLocator" class="examples.DefaultServiceLocator">
        <!-- inject any dependencies required by this locator bean -->
    </bean><bean id="clientService"
        factory-bean="serviceLocator"
        factory-method="createClientServiceInstance"/><bean id="accountService"
        factory-bean="serviceLocator"
        factory-method="createAccountServiceInstance"/>

    以下示例显示了相应的Java类:

    public class DefaultServiceLocator {
    ​
        private static ClientService clientService = new ClientServiceImpl();
    ​
        private static AccountService accountService = new AccountServiceImpl();
    ​
        public ClientService createClientServiceInstance() {
            return clientService;
        }
    ​
        public AccountService createAccountServiceInstance() {
            return accountService;
        }
    }

     代码演示:

    package spring1;
    
    public class Dog {
        
          /** 姓名 **/
        private String name;
    
        /** 年龄 **/
        private int age;
    
        /**
         * 默认构造函数
         */
        public Dog() {
        }
    
        /**
         * 构造函数
         * @param name 姓名
         * @param age  年龄
         */
        public Dog(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public void sayHello() {
            System.out.println("大家好, 我叫" + getName() + ", 我今年" + getAge() + "岁了");
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
    }
    public class DogFactory {
        
         public Dog newInstance(String name, int age) {
                return new Dog(name, age);
            }
    
    }
    public class DogStaticFactory {
        
         // 静态工厂方法
        public static Dog newInstance(String name, int age) {
            // 返回需要的Bean实例
            return new Dog(name, age);
        }
    
    }

    pom.xml

    <properties>
            <spring-version>4.3.20.RELEASE</spring-version>
        </properties>
    
        <dependencies>
    
            <!-- https://mvnrepository.com/artifact/junit/junit -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring-version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>${spring-version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>${spring-version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>${spring-version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
                <version>${spring-version}</version>
            </dependency>
        </dependencies>

    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"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
    
        <!-- ====================实例化bean的方式Begin==================== -->
        <!-- 默认构造实例化 -->
        <bean id="dog1" class="spring1.Dog" />
    
        <!-- 指定构造器实例化 -->
        <bean id="dog2" class="spring1.Dog">
            <!-- 指定构造器参数 index对应构造器中参数的位置 -->
            <!-- 也可以通过指定参数类型,指定参数名称来注入属性 -->
            <constructor-arg index="0" value="大黄" />
            <constructor-arg index="1" value="2" />
        </bean>
        <!-- ====================实例化bean的方式End==================== -->
    
        <!-- 实例工厂方法实例化 -->
        <bean id="dogFactory" class="spring1.DogFactory" />
        <!-- 不能指定class属性,此时必须使用factory-bean属性来指定工厂Bean,factory-method属性指定实例化Bean的方法 -->
        <bean id="dog4" factory-bean="dogFactory"
            factory-method="newInstance">
            <constructor-arg index="0" value="小明" />
            <constructor-arg index="1" value="3" />
        </bean>
    
        <!-- 静态工厂方法实例化 -->
        <bean id="dog3" class="spring1.DogStaticFactory"
            factory-method="newInstance">
            <!-- 指定构造器参数 index对应构造器中参数的位置 -->
            <constructor-arg index="0" value="小明" />
            <constructor-arg index="1" value="3" />
        </bean>
    </beans>

    测试类

    public class Test1 {
        
           ClassPathXmlApplicationContext ctx = null;
    
            @Before
            public void initXmlBeanFactory() {
                System.out.println("
    ========测试方法开始=======
    ");
                ctx = new ClassPathXmlApplicationContext("spring.xml");
            }
    
            @After
            public void after() {
                System.out.println("
    ========测试方法结束=======
    ");
            }
    
            @Test
            public void test1() {
                // 默认构造器
                System.out.println("默认构造器");
                Dog dog1 = ctx.getBean("dog1", Dog.class);
                dog1.sayHello();
            }
    
            @Test
            public void test2() {
                // 指定构造器
                System.out.println("有参构造器");
                Dog dog2 = ctx.getBean("dog2", Dog.class);
                dog2.sayHello();
            }
    
            @Test
            public void test3() {
                // 静态工厂
                System.out.println("静态工厂");
                Dog dog3 = ctx.getBean("dog3", Dog.class);
                dog3.sayHello();
            }
    
            @Test
            public void test4() {
                // 实例工厂
                System.out.println("实例工厂");
                Dog dog4 = ctx.getBean("dog4", Dog.class);
                dog4.sayHello();
            }
    
    }

    测试结果:

    ========测试方法开始=======
    默认构造器
    大家好, 我叫null, 我今年0岁了
    
    ========测试方法结束=======
    
    
    ========测试方法开始=======
    有参构造器
    大家好, 我叫大黄, 我今年2岁了
    
    ========测试方法结束=======
    
    
    ========测试方法开始=======
    
    静态工厂
    大家好, 我叫小明, 我今年3岁了
    
    ========测试方法结束=======
    
    
    ========测试方法开始=======
    
    实例工厂
    大家好, 我叫小明, 我今年3岁了
    
    ========测试方法结束=======
  • 相关阅读:
    c/cpp枚举练习
    数据类型的标识
    引用变量
    cocos2dx 3.3 笔记
    希望获取到页面中所有的checkbox怎么做?
    如何判断某变量是否为数组数据类型?
    驼峰函数写法
    trim()函数
    js 获取页面可视区域宽高
    全屏滚动插件
  • 原文地址:https://www.cnblogs.com/dalianpai/p/12009517.html
Copyright © 2011-2022 走看看