当前位置:   article > 正文

Spring创建bean的四种方式_spring如何创建一个bean

spring如何创建一个bean

首先介绍一下关于Spring的几个重要概念

Spring

Spring容器的概念,容器这个名字起的非常好,容器可以放很多的东西,我们的程序启动的时候会创建spring容器,会给spring容器一个清单,清单中列出了需要创建的对象以及对象依赖关系,spring容器会创建和组装好清单中的对象,然后将这些对象存放在spring容器中,当程序中需要使用的时候,可以到容器中查找获取,然后直接使用。

IOC:控制反转

对象A依赖于对象B,之前使用B对象的时候都需要自己去创建和组装,而现在这些创建和组装都交给spring容器去给完成了,使用者只需要去spring容器中查找需要使用的对象就可以了;这个过程中B对象的创建和组装过程反转了,所以叫控制反转,IOC是面向对象编程中的一种设计原则,主要是为了降低系统代码的耦合度,让系统利于维护和扩展。

DI:依赖注入

依赖注入是spring容器中创建对象时给其设置依赖对象的方式,比如给spring一个清单,清单中列出了
需要创建B对象以及其他的一些对象(可能包含了B类型中需要依赖对象),此时spring在创建B对象的
时候,会看B对象需要依赖于哪些对象,然后去查找一下清单中有没有包含这些被依赖的对象,如果有
就去将其创建好,然后将其传递给B对象;可能B需要依赖于很多对象,B创建之前完全不需要知道其他
对象是否存在或者其他对象在哪里以及被他们是如何创建,而spring容器会将B依赖对象主动创建好并将
其注入到B中去,比如spring容器创建B的时候,发现B需要依赖于A,那么spring容器在清单中找到A的
定义并将其创建好之后,注入到B对象中。

总之

  1. IOC控制反转,是一种设计理念,将对象创建和组装的主动控制权利交给了spring容器去做,控制的动作被反转了,降低了系统的耦合度,利于系统维护和扩展,主要就是指需要使用的对象的组装控制权被反转了,之前是自己要做的,现在交给spring容器做了。
  2. DI依赖注入,表示spring容器中创建对象时给其设置依赖对象的方式,通过某些注入方式可以让系统更灵活,比如自动注入等可以让系统变得很灵活。
  3. spring容器:主要负责容器中对象得创建、组装、对象查找、对象生命周期得管理等操作。

容器创建bean实例的方法

  1. 通过反射调用构造方法创建bean对象
  2. 通过静态工厂方法创建bean对象
  3. 通过实例工厂方法创建bean对象
  4. 通过FactoryBean创建bean对象

测试bean

public class Blog {

    private String date;

    private String title;

    private String author;

    private int num;

    public Blog() {
    }

    public Blog(String date, String title, String author, int num) {
        this.date = date;
        this.title = title;
        this.author = author;
        this.num = num;
    }
    
	//省略了getter 和 setter方法
	
    @Override
    public String toString() {
        return "Blog{" +
                "date='" + date + '\'' +
                ", title='" + title + '\'' +
                ", author='" + author + '\'' +
                ", num=" + num +
                '}';
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

通过反射调用构造方法创建bean对象

调用类的构造方法获取对应的bean实例,是使用最多的方式,这种方式只需要在xml bean元素中指定擦class属性,spring容器内部会自动调用该类型的构造方法来创建bean对象,将其放在容器中以供使用。

<!--通过无参构造创建bean-->
<bean id="noArgBlog" class="com.demo.blog.Blog"/>

<!--通过有参构造创建bean-->
<bean id="argBlog" class="com.demo.blog.Blog">
    <constructor-arg index="0" value="2022-06-10"/>
    <constructor-arg index="1" value="spring系列-01"/>
    <constructor-arg index="2" value="wangms"/>
    <constructor-arg index="3" value="1"/>
</bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

constructor-arg:用于指定构造方法的参数值
index:构造方法中参数的位置,从0开始,依次递增
value:指定参数的值
ref:当插入的值为容器内其他bean的时候,这个值为容器中对应bean的名称

测试用例
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beansBlog.xml");
Blog noArgBlog = context.getBean("noArgBlog", Blog.class);
System.out.println(noArgBlog);
Blog argBlog = context.getBean("argBlog", Blog.class);
System.out.println(argBlog);
  • 1
  • 2
  • 3
  • 4
  • 5
测试结果
通过无参构造函数创建的bean
Blog{date='null', title='null', author='null', num=0}
Blog{date='2022-06-10', title='spring系列-01', author='wangms', num=1}
  • 1
  • 2
  • 3

通过静态工厂方法创建bean对象

创建一个静态工厂类,用于生成Blog对象。

public class BlogStaticFactory {

    /**静态无参方法创建*/
    public static Blog noArgBlogBuilder()
    {
        Blog blog = new Blog();
        blog.setTitle("无参静态方法创建的...");
        return blog;
    }

    /**静态有参方法创建*/
    public static Blog argBlogBuilder(String date, String title, String author, int num)
    {
        return new Blog(date, title, author, num);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

spring容器会自动调用静态工厂的静态方法获取指定的对象,将其放在容器中以供使用

<!-- 通过工厂静态无参方法创建bean对象 -->
<bean id="noArgStaticBlogBuilder" class="com.demo.blog.BlogStaticFactory" factory-method="noArgBlogBuilder"/>
<!-- 通过工厂静态有参方法创建bean对象 -->
<bean id="argStaticBlogBuilder" class="com.demo.blog.BlogStaticFactory" factory-method="argBlogBuilder">
    <constructor-arg index="0" value="2022-06-10"/>
    <constructor-arg index="1" value="有参静态方法创建的..."/>
    <constructor-arg index="2" value="wangms2"/>
    <constructor-arg index="3" value="2"/>
</bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

class:指定静态工厂完整的类名
factory-method:静态工厂中的静态方法,返回需要的对象
constructor-arg:用于指定静态方法参数的值,用法和上面介绍的构造方法一样

spring容器启动的时候会自动调用BlogStaticFactory中的noArgBlogBuilder静态方法获取Blog对象,将其作为noArgStaticBlogBuilder名称对应的bean对象放在spring容器中。
会调用BlogStaticFactory的argBlogBuilder方法,并且会传入需要的参数,得到返回的Blog对象,将其作为argStaticBlogBuilder名称对应的bean对象放在spring容器中。

测试用例
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beansBlog.xml");
Blog noArgBlog = context.getBean("noArgStaticBlogBuilder", Blog.class);
System.out.println(noArgBlog);
Blog argBlog = context.getBean("argStaticBlogBuilder", Blog.class);
System.out.println(argBlog);
  • 1
  • 2
  • 3
  • 4
  • 5
测试结果
Blog{date='null', title='无参静态方法创建的...', author='null', num=0}
Blog{date='2022-06-10', title='有参静态方法创建的...', author='wangms2', num=2}
  • 1
  • 2

通过实例工厂方法创建bean对象

让spring容器去调用某些对象的某些实例方法来生成bean对象放在容器中以供使用。

定义一个实例工厂

public class BlogFactory {
    /**无参方法*/
    public Blog noArgBuilder()
    {
        return new Blog();
    }
    /**有参方法*/
    public Blog argBuilder(String date, String title, String author, int num)
    {
        return new Blog(date, title, author, num);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
<!-- 定义一个工厂实例 -->
<bean id="blogFactory" class="com.demo.blog.BlogFactory"/>
<!-- 通过实例工厂无参方法创建bean对象 -->
<bean id="blog1" class="com.demo.blog.BlogStaticFactory" factory-bean="blogFactory" factory-method="noArgBuilder"/>
<!-- 通过实例工厂有参方法创建bean对象 -->
<bean id="blog2" class="com.demo.blog.BlogStaticFactory" factory-bean="blogFactory" factory-method="argBuilder">
    <constructor-arg index="0" value="2022-06-10"/>
    <constructor-arg index="1" value="实例工厂有参方法创建的..."/>
    <constructor-arg index="2" value="wangms2"/>
    <constructor-arg index="3" value="2"/>
</bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

spring容器以factory-bean的值为bean名称查找对应的bean对象,然后调用该对象中factory-method
属性值指定的方法,将这个方法返回的对象作为当前bean对象放在容器中供使用

blog1对应的bean是通过BlogFactory的noArgBuilder方法生成的;
blog2对应的bean是通过BlogFactory的argBuilder方法生成的。

测试用例

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beansBlog.xml");
Blog noArgBlog = context.getBean("blog1", Blog.class);
System.out.println(noArgBlog);
Blog argBlog = context.getBean("blog2", Blog.class);
System.out.println(argBlog);
  • 1
  • 2
  • 3
  • 4
  • 5

测试结果

Blog{date='null', title='null', author='null', num=0}
Blog{date='2022-06-10', title='实例工厂有参方法创建的...', author='wangms2', num=2}
  • 1
  • 2

通过FactoryBean来创建bean对象

前面我们学过了BeanFactory接口,BeanFactory是spring容器的顶层接口,而这里要说的是
FactoryBean,也是一个接口,这两个接口很容易搞混淆,FactoryBean可以让spring容器通过这个接口
的实现来创建我们需要的bean对象。
源码如下

public interface FactoryBean<T> { 
	/*** 返回创建好的对象 */ 
	@Nullable T getObject() throws Exception; 
	
	/*** 返回需要创建的对象的类型 */ 
	@Nullable Class<?> getObjectType();
	 
	/** * bean是否是单例的 **/ 
	default boolean isSingleton() { 
		return true; 
	} 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

接口中有3个方法,前面2个方法需要我们去实现,getObject方法内部由开发者自己去实现对象的创
建,然后将创建好的对象返回给Spring容器,getObjectType需要指定我们创建的bean的类型;最后一
个方法isSingleton表示通过这个接口创建的对象是否是单例的,如果返回false,那么每次从容器中获取
对象的时候都会调用这个接口的getObject() 去生成bean对象。
最后一种方式因平常不怎么用,所以没有贴代码,感兴趣的可以实现接口试试。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/241616
推荐阅读
相关标签
  

闽ICP备14008679号