当前位置: 移动技术网 > IT编程>开发语言>Java > Spring 创建Bean的6种方式

Spring 创建Bean的6种方式

2019年06月21日  | 移动技术网IT编程  | 我要评论

 

前言

本文讲解了在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 还为我们提供了更多类似的注解。

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

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

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

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功能的扩展。

测试代码和以上一样

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

 

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

 

完结。

===========

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网