Spring创建Bean的6种方式详解

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

1111

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

在resources下创建如下文件。META-INF/spring.factories.

Spring Boot 在启动的时候将会扫描该文件,从何获取到配置类UserConfiguration。

22222222

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

333333333333

测试代码和以上一样

Location location = context.getBean(Location.class);
location.run();

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

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

(0)

相关推荐

  • spring中通过ApplicationContext getBean获取注入对象的方法实例

    用SpringContextUtil实现ApplicationContextAware package util; import java.util.Locale; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; pub

  • Spring通过ApplicationContext主动获取bean的方法讲解

    问题1: 有个异步线程Runnable里面需要用到dao,无法通过AutoWired和compoment注解传递进来. 于是希望通过Spring context主动去获取bean. 问题2: getBean(name)获取失败. 解决: 默认的dao的name=类名(首字母小写) 例如: 接口名称:TemplateDao 则getName("templateDao")即可 通用的SpringContextUtil获取Bean 1.实现ApplicationContextAware接口

  • Spring注入Bean的一些方式总结

    通过注解注入Bean 背景 我们谈到Spring的时候一定会提到IOC容器.DI依赖注入,Spring通过将一个个类标注为Bean的方法注入到IOC容器中,达到了控制反转的效果.那么我们刚开始接触Bean的时候,一定是使用xml文件,一个一个的注入,就例如下面这样. <bean id="bean" class="beandemo.Bean" /> 我们的项目一般很大的话,就需要成千上百个Bean去使用,这样写起来就很繁琐.那么Spring就帮我们实现了一

  • 详解SpringBoot 多线程处理任务 无法@Autowired注入bean问题解决

    在多线程处理问题时,无法通过@Autowired注入bean,报空指针异常, 在线程中为了线程安全,是防注入的,如果要用到这个类,只能从bean工厂里拿个实例. 解决方法如下: 1.创建一个工具类代码: package com.hqgd.pms.common; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.spri

  • Spring创建Bean的6种方式详解

    前言 本文讲解了在Spring 应用中创建Bean的多种方式,包括自动创建,以及手动创建注入方式,实际开发中可以根据业务场景选择合适的方案. 方式1: 使用Spring XML方式配置,该方式用于在纯Spring 应用中,适用于简单的小应用,当应用变得复杂,将会导致XMl配置文件膨胀 ,不利于对象管理. <bean id="xxxx" class="xxxx.xxxx"/> 方式2: 使用@Component,@Service,@Controler,@R

  • Spring实例化bean的四种方式详解

    目录 一.bean实例化——构造方法(常用) 二.bean实例化——静态工厂(了解) 三.bean实例化——实例工厂(了解) 四.bean实例化——FactoryBean(实用) 一.bean实例化——构造方法(常用) bean本质上就是对象,创建bean使用构造方法完成 BookDao接口: public interface BookDao { public void save(); } BookDaoImpl实现类,利用构造方式提供可访问的构造方法,输出相应字符串: import com.i

  • Spring为IOC容器注入Bean的五种方式详解

    这篇文章主要介绍了Spring为IOC容器注入Bean的五种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 @Import导入组件,id默认是组件的全类名 //类中组件统一设置.满足当前条件,这个类中配置的所有bean注册才能生效: @Conditional({WindowsCondition.class}) @Configuration @Import({Color.class,Red.class,MyImportSelector

  • Spring中实例化bean的四种方式详解

    前言 在介绍Bean的实例化的方式之前,我们首先需要介绍一下什么是Bean,以及Bean的配置方式. 如果把Spring看作一个大型工厂,那么Spring容器中的Bean就是该工厂的产品.要想使用Spring工厂生产和管理Bean,就需要在配置文件中指明需要哪些Bean,以及需要使用何种方式将这些Bean装配到一起. Spring容器支持两种格式的配置文件,分别为Properties文件格式和xml文件格式,而在实际的开发当中,最常使用的额是xml文件格式,因此在如下的讲解中,我们以xml文件格

  • JavaEE的进程,线程和创建线程的5种方式详解

    目录 一.认识进程.线程 1.1什么是进程 进程的调度 并发式执行 1.2认识线程 1.3进程.线程之前的区别和联系(面试题) 创建线程的几种方式 总结 一.认识进程.线程 1.1什么是进程 进程process/task.“进程"是计算机完成一个工作的"过程” 设备上一个正在运行的程序,就是一个进程.比如你打开的QQ就是一个进程,正在和别人聊天的微信也是一个进程.进程是系统进行资源分配的基本单位. 当我们打开任务管理器就可以看到,当前操作系统中正在运行的进程. 要想让一个进程真正的运行

  • Spring在代码中获取bean的几种方式详解

    方法如下 方法一:通过读取XML文件反射生成对象 方法二:通过Spring提供的utils类获取ApplicationContext对象 方法三:继承自抽象类ApplicationObjectSupport 方法四:继承自抽象类WebApplicationObjectSupport 方法五:实现接口ApplicationContextAware 方法六:通过Spring提供的ContextLoader 获取spring中bean的方式总结: 方法一:通过读取XML文件反射生成对象 Applica

  • Spring 依赖注入的几种方式详解

    IoC 简介 平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过Spring容器帮我们new指定实例并且将实例注入到需要该对象的类中. 依赖注入的另一种说法是"控制反转".通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员. 而控制反转是指new实例工作不由我们程序员来做而是交给Spring容器来做.

  • Spring Boot开启的2种方式详解

    Spring Boot依赖 使用Spring Boot很简单,先添加基础依赖包,有以下两种方式 1. 继承spring-boot-starter-parent项目 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.RELEASE</versi

  • Spring创建bean对象三种方式代码实例

    一.使用无参构造方法创建 二.使用静态工厂创建 三.使用实例工厂创建 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们.

  • Spring成员对象注入的三种方式详解

    目录 一.@Autowired注解 @Qualifier @Primary 二.@Resource注解 三.@Inject和@Named注解 总结 当一个类运行需要调用一个成员对象,成员对象也是被容器类托管的类对象时,则可以用依赖注入创建成员对象.让容器类来帮你创建成员对象. 官网链接:Annotation-based Container Configuration 前置: 容器类AppConfig import org.springframework.context.annotation.Co

随机推荐