欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring 创建Bean的6种方式

程序员文章站 2022-06-28 19:35:30
前言 本文讲解了在Spring 应用中创建Bean的多种方式,包括自动创建,以及手动创建注入方式,实际开发中可以根据业务场景选择合适的方案。 方式1: 使用Spring XML方式配置,该方式用于在纯Spring 应用中,适用于简单的小应用,当应用变得复杂,将会导致XMl配置文件膨胀 ,不利于对象管 ......

 

前言

本文讲解了在spring 应用中创建bean的多种方式,包括自动创建,以及手动创建注入方式,实际开发中可以根据业务场景选择合适的方案。

方式1:

使用spring xml方式配置,该方式用于在纯spring 应用中,适用于简单的小应用,当应用变得复杂,将会导致xml配置文件膨胀 ,不利于对象管理。

<bean id="xxxx"  class="xxxx.xxxx"/>

方式2:

使用@component,@service,@controler,@repository注解

这几个注解都是同样的功能,被注解的类将会被spring 容器创建单例对象。

@component : 侧重于通用的bean类

@service:标识该类用于业务逻辑

@controler:标识该类为spring mvc的控制器类

@repository: 标识该类是一个实体类,只有属性和setter,getter

@component
public class user{
}

当用于spring boot应用时,被注解的类必须在启动类的根路径或者子路径下,否则不会生效。

如果不在,可以使用@componentscan标注扫描的路径。

spring xml 也有相关的标签<component-scan />

@componentscan(value={"com.microblog.blog","com.microblog.common"})
public class microblogblogapplication {
    public static void main(string args[]){
        springapplication.run(microblogblogapplication.class,args);
    }
}

 

方式3:

使用@bean注解,这种方式用在spring boot 应用中。

@configuration 标识这是一个spring boot 配置类,其将会扫描该类中是否存在@bean 注解的方法,比如如下代码,将会创建user对象并放入容器中。

@conditionalonbean 用于判断存在某个bean时才会创建user bean.

这里创建的bean名称默认为方法的名称user。也可以@bean("xxxx")定义。

@configuration
public class userconfiguration{
     
      @bean
    @conditionalonbean(location.class) public user user(){ return new user(); } }

 

spring boot 还为我们提供了更多类似的注解。

Spring 创建Bean的6种方式

也和方式2一样,也会存在扫描路径的问题,除了以上的解决方式,还有使用spring boot starter 的解决方式

在resources下创建如下文件。meta-inf/spring.factories.

spring boot 在启动的时候将会扫描该文件,从何获取到配置类userconfiguration。

Spring 创建Bean的6种方式

spring.factories.

org.springframework.boot.autoconfigure.enableautoconfiguration=com.log.config.userconfiguration

 

如果不成功,请引入该依赖

    <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-configuration-processor</artifactid>
            <optional>true</optional>
        </dependency>    

 

这个方式也是创建springboot-starter的方式。

 

方式4:

使用注解@import,也会创建对象并注入容器中

@import(user.class)
public class microbloguserwebapplication {
    public static void main(string args[]) {
        springapplication.run(microbloguserwebapplication.class, args);
    }
}

方式5:

使用importselector或者importbeandefinitionregistrar接口,配合@import实现。

在使用一些spring boot第三方组件时,经常会看到@enablexxx来使能相关的服务,这里以一个例子来实现。

 

创建测试类

@slf4j
public class house {

    public void run(){

        log.info("house  run ....");
    }
}

@slf4j
public class user {


    public void run(){

        log.info("user  run ....");

    }

}

@slf4j
public class student {

    public void run(){

        log.info("student  run ....");

    }

}

 

 

实现importselector接口

selectimports方法的返回值为需要创建bean的类名称。这里创建user类。

@slf4j
public class myimportselector implements importselector {

    @override
    public string[] selectimports(annotationmetadata annotationmetadata) {


        log.info("myimportselector selectimports ...");
        return new string[]{
            user.class.getname()};
    }
}

 

实现importbeandefinitionregistrar接口

beandefinitionregistry.registerbeandefinition用于设置需要创建bean的类名称。这里创建house类。

@slf4j
public class myimportbeandefinitionregistrar implements importbeandefinitionregistrar {
    @override
    public void registerbeandefinitions(annotationmetadata annotationmetadata, beandefinitionregistry beandefinitionregistry) {

        log.info("myimportbeandefinitionregistrar  registerbeandefinitions .....");
        beandefinition beandefinition =  new rootbeandefinition(house.class.getname());
        beandefinitionregistry.registerbeandefinition(house.class.getname(),beandefinition);
    }
}

 

创建一个配置类

这里创建student类。

@configuration
public class importautoconfiguration {

    @bean
    public student student(){
        return new student();
    }
}

 

创建enableimportselector注解

enableimportselector注解上使用@import,引入以上的三个类。

@retention(retentionpolicy.runtime)
@documented
@target(elementtype.type)
@import({myimportselector.class,importautoconfiguration.class,myimportbeandefinitionregistrar.class})
public @interface enableimportselector {

    string value();

}

 

 测试

@enableimportselector(value = "xxx")
@springbootapplication
public class importdemoapplication {

    public static void main(string[] args) {
        configurableapplicationcontext context =  springapplication.run(importdemoapplication.class, args);

        user user =  context.getbean(user.class);
        user.run();

        student student =  context.getbean(student.class);
        student.run();

        house house =  context.getbean(house.class);
        house.run();

    }

}

 

输出,可以看到,三个类user student house都创建成功,都可从spring 容器中获取到。

2019-06-20 17:53:39.528  info 27255 --- [           main] com.springboot.importselector.pojo.user  : user  run ....
2019-06-20 17:53:39.530  info 27255 --- [           main] c.s.importselector.pojo.student          : student  run ....
2019-06-20 17:53:39.531  info 27255 --- [           main] c.springboot.importselector.pojo.house   : house  run ....

 

 

方式6

手动注入bean容器,有些场景下需要代码动态注入,以上方式都不适用。这时就需要创建 对象手动注入。

通过defaultlistablebeanfactory注入。

registersingleton(string beanname,object object);

这里手动使用new创建了一个location对象。并注入容器中。

 


@component
public class locationregister implements beanfactoryaware {

@override
public void setbeanfactory(beanfactory beanfactory) throws beansexception {
defaultlistablebeanfactory listablebeanfactory = (defaultlistablebeanfactory)beanfactory;
location location = new location();
listablebeanfactory.registersingleton("location1",location);
}
}

这种方式的应用场景是为接口创建动态代理对象,并向spring容器注册。

比如mybatis中的mapper接口,mapper没有实现类,启动时创建动态代理对象,将该对象注册到容器中,使用时只要@autowired注入即可使用,调用接口方法将会被代理拦截,进而调用相关的sqlsession执行相关的sql业务逻辑。

 

可以看以下它的继承体系

defaultlistablebeanfactory 是configurablelistablebeanfactory的实现类。是对beanfactory功能的扩展。

Spring 创建Bean的6种方式

测试代码和以上一样

location location =  context.getbean(location.class);
location.run();

 

本文的相关代码位于 实例代码 测试类

 

完结。

===========