温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Spring定义Bean的方式有哪些

发布时间:2023-05-09 15:11:04 来源:亿速云 阅读:108 作者:zzz 栏目:开发技术

本文小编为大家详细介绍“Spring定义Bean的方式有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring定义Bean的方式有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

    1.通过XML的方式来生成一个bean

    最简单也是最原始的一种方式,通过XML来定义一个bean,我们来看下其过程

    1)创建entity,命名为Student

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Student implements Serializable {
     
        private static final long serialVersionUID = -2088281526481179972L;
        private int id;
        private String name;
        private int age;
    }

    2)在beans.xml中定义Student

        <!-- 1.空值的student -->
        <bean id="studentNoValue" class="domain.Student"/>
     
        <!-- 2.带值的student -->
        <bean id="student" class="domain.Student">
            <property name="id" value="11"/>
            <property name="age" value="22"/>
            <property name="name" value="jack"/>
        </bean>
     
        <!-- 3.全参构造:使用成员变量名称对应 -->
        <bean id="studentConstruct" class="domain.Student">
            <constructor-arg name="age" value="22"></constructor-arg>
            <constructor-arg name="id" value="11"></constructor-arg>
            <constructor-arg name="name" value="jack"></constructor-arg>
        </bean>
     
        <!-- 4.全参构造:使用成员变量index对应 -->
        <bean id="studentConstruct2" class="domain.Student">
            <constructor-arg index="0" value="11"></constructor-arg>
            <constructor-arg index="1" value="jack"></constructor-arg>
            <constructor-arg index="2" value="22"></constructor-arg>
        </bean>
     
        <!-- 5.全参构造:使用成员变量类型对应 -->
        <bean id="studentConstruct3" class="domain.Student">
            <constructor-arg type="int" value="11"></constructor-arg>
            <constructor-arg type="java.lang.String" value="jack"></constructor-arg>
            <constructor-arg type="int" value="22"></constructor-arg>
        </bean>

    总结:可以看到,创建bean的方式多种多样,我们可以通过属性来赋值<property>,也可以通过构造参数来赋值<constructor>,关于构造赋值以上展示了三种方式,我们可以根据自己的需求来选择对应的方式。

    3)测试bean

    public class ApplicationContextTest {
     
        @Test
        public void testXml(){
            ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
            Student studentNoValue = (Student) applicationContext.getBean("studentNoValue");
            Student studentFullValue = (Student) applicationContext.getBean("studentFullValue");
            System.out.println(studentNoValue);
            System.out.println(studentFullValue);
     
     
            Student studentConstruct1 = (Student) applicationContext.getBean("studentConstruct");
            Student studentConstruct2 = (Student) applicationContext.getBean("studentConstruct2");
            Student studentConstruct3 = (Student) applicationContext.getBean("studentConstruct3");
            System.out.println(studentConstruct1);
            System.out.println(studentConstruct2);
            System.out.println(studentConstruct3);
     
            Book bookChinese = (Book) applicationContext.getBean("bookChinese");
            System.out.println(bookChinese);
        }
    }
    // res:
    Student(id=0, name=null, age=0)
    Student(id=11, name=jack, age=22)
    Student(id=11, name=jack, age=22)
    Student(id=11, name=jack, age=22)
    Student(id=11, name=jack, age=22)

    2.<bean>标签深入了解

    我们刚才介绍了最基本的Bean使用方式,大家会发现<bean>标签还有其他的属性,比如name/scope/lazy-init/init-method/...等,这些是做什么用的呢?我们在实际的工作中怎么使用呢?

    1)name属性

    在介绍name属性之前,我们先来看下ApplicationContext.getBean()的两种方式

    * ApplicationContext.getBean(String name)

    * ApplicationContext.getBean(Class<T> requiredType)

    第一种方式的这个name是什么呢?我们应该如何定义,又该如何使用呢?

    // 上文示例中,我们只是指定了Bean的id和class,如下所示
    <bean id="studentNoValue" class="domain.Student" />
        
    // 具体获取bean的方式如下:
    Student studentNoValue = (Student) applicationContext.getBean("studentNoValue");
     
    // 可以看到,在没有指定bean的name属性的时候,默认使用id来获取bean,当做name使用
    // 如果我们不想根据id获取,那就需要主动指定bean的name属性,如下所示:
    <bean id="studentNoValue" class="domain.Student" name="stuName"/>
    // 这样在获取的时候,就需要使用指定的名称来获取,再根据id来获取的时候就会报错了
    Student studentNoValue = (Student) applicationContext.getBean("stuName");
        * 根据Class来获取这种方式很好理解,这个不关心你定义的id或者name是什么,使用如下:
    
    Student studentNoValue = (Student) applicationContext.getBean(Student.class);

    2)scope属性

    可以看到,在使用scope属性的时候,提示有两种输入值,分别是singleton/prototype

    这个就代表了Spring-Bean的两种创建模式,单例模式和原型模式

    * Spring默认使用单例模式来创建Bean,通过ApplicationContext所获得的bean都是同一个bean(在beanName相同的情况下),我们可以来验证下

    Student studentNoValue = (Student) applicationContext.getBean("stuName");
    Student studentNoValue2 = (Student) applicationContext.getBean("stuName");
     
    System.out.println(studentNoValue == studentNoValue2);// true

    可以看到的是结果输入为true,从工厂类中两次获取的stuName是同一个对象。

    * 下面来验证下原型模式

    原型模式:每次获取的bean都为一个新的对象

    // 修改beans.xml中studentNoValue的scope为prototype
    <bean id="studentNoValue" class="domain.Student" name="stuName" scope="prototype"/>
     
    // 然后执行上面的测试代码
    Student studentNoValue = (Student) applicationContext.getBean("stuName");
    Student studentNoValue2 = (Student) applicationContext.getBean("stuName");
     
    System.out.println(studentNoValue == studentNoValue2);// false

    可以看到,输出结果为false,原型模式下从工厂类两次获取的stuName不是同一个对象。

    3)init-method和destroy-method方法

    见名知意,init-method应该是初始化方法的意思,destroy-method应该是销毁方法的意思。那怎么使用呢?

    // 在Student.java中添加init()方法和destroy()方法
    public void init(){
        System.out.println("student init...");
    }
     
    public void destroy(){
        System.out.println("student destroy...");
    }
     
    // 在beans.xml中studentNoValue的bean上添加 init-method和destroy-method
    <bean id="studentNoValue" class="domain.Student" name="stuName" init-method="init" destroy-method="destroy"/>
     
    // 测试方法如下:
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
    Student studentNoValue = (Student) applicationContext.getBean("stuName");
     
    applicationContext.close();
     
    // 执行结果:
    student init...
    student destroy...

    总结:在获取bean的时候init()方法被执行,在容器被销毁的时候,执行了destroy()方法

    根据这个,我们可以在初始化bean和销毁bean的时候做点什么,比如关闭连接,保存记录之类的操作。

    延伸:那么初始化init()方法在构造方法之前调用,还是之后调用呢?读者可以自行验证下

    总结:还有一些其他属性,笔者就不再一一验证了,下面说一下通过JavaConfig的方法来实现bean的定义。

    3.JavaConfig方式的bean定义

    JavaConfig是Spring4.x推荐的配置方式,可以完全替代XML的方式定义。

    1)如何定义一个Bean

    // 创建一个类,命名为SpringConfiguration
    @Configuration
    public class SpringConfiguration {
        @Bean
        public Student student(){
            return new Student(11,"jack",22);
        }
    }
     
    // 使用bean
    AnnotationConfigApplicationContext applicationContext
                    = new AnnotationConfigApplicationContext(SpringConfiguration.class);
    Student student = (Student) applicationContext.getBean("student")
    System.out.println(student);
     
    // res:
    Student(id=11, name=jack, age=22)

    相对于XML的使用方式而言,JavaConfig的使用方式基本是同步的

    * @Configuration等同于<beans></beans>

    * @Bean等同于<bean></bean>

    * 通过AnnotationConfigApplicationContext来加载JavaConfig

    * 方法名student()就等同于<bean>中的id,默认方法名就是beanName

    2)@Bean的其他参数

    * name属性等同于<bean>的name

    * initMethod属性等同于<bean>的init-method

    * destroyMethod属性等同于<bean>的destroy-method

    * scope这个比较奇怪,不属于@Bean的参数,这是一个单独的注解,使用方式如下

    @Bean(name = "stu",autowire = Autowire.BY_TYPE)
    @Scope(value = "singleton")
    public Student student(){
        return new Student(11,"jack",22);
    }

    读到这里,这篇“Spring定义Bean的方式有哪些”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI