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

Spring创建Bean的6种方式详解

2019年07月19日  | 移动技术网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();

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

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

相关文章:

验证码:
移动技术网