还只会用 @Service 注册 Bean 吗? | 七日打卡

前言

众所周知,在咱们平时的开发中,Spring这个框架已经环绕了整个项目,不是说咱们不能不用Spring,而是这样作的代价太大了。每次面试,老是会问道Spring IOC、AOP、事务等等,今天这篇的话是猛男我刚工做碰到的一个面试真题,可怜我那时只知道@Service。而后就回去等通知了,到如今尚未给我通知。面试

另外的话,今天这篇会讲几种注入方式,至于原理好哥哥们就先别想了(别打我脸就行),这随便拿一个出来都的讲源码讲一遍,主要须要依赖的东西优势多,因此找个机会将Spring IOC 那一块的源码弄出来讲说,这一篇的话主要是讲个大概。
打脸spring

正题

1 @Service、@Component、@Repository、@Controller

这种方式就很简单,像@Service、@Repository其实仍是用的@Component,在注解里面点击去看就知道了,须要注意的点是这种方式须要用@ComponentScan配置一个一个扫包范围。为何不用@Component这一个呢,主要是Spring为了区分Bean的类型。@Repository做用于持久层,@Service 做用于业务逻辑层,@Controller做用于表现层(spring-mvc的注解)数组

@Componentpublic class ApproveCenterServiceImpl implements ApproveCenterService {
}@Servicepublic class ApproveCenterServiceImpl implements ApproveCenterService {
}@Repositorypublic class ApproveCenterServiceImpl implements ApproveCenterService {
}复制代码

2 @Bean 和@Configuration

这种方式是否是很熟悉,经常使用于标注配置类,最简单的一个例子就是咱们使用SpringBoot 的时候须要手动注册一个Bean``叫作RestTemplate`spring-mvc

@Configurationpublic class RestTemplateConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate();
    }
}复制代码

3 使用@Import

@Import 注解能够注册三种类型的Bean,第一种就是普通类,第二种DefinitionRegistrar类,第三种就是ImportSelectormvc

3.1 普通类

/**
 * @author xiejianwei
 */@Import(MessageRecord.class)public @interface ImportBean {
}复制代码

3.2 DefinitionRegistrar

实现了ImportBeanDefinitionRegistrar,这种方式在实现类中提供了一个注册器,有一个很熟悉的注解@MapperScan好哥哥们点进去看看就明白了。app

@Import(MapperScannerRegistrar.class)public @interface MapperScan {
}public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {  /**
   * 主要是这个方法,在参数中提供了BeanDefinitionRegistry这个注册器,能够手动向容器中注入bean
   */
  @Override
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    AnnotationAttributes mapperScanAttrs = AnnotationAttributes
        .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));if (mapperScanAttrs != null) {
      registerBeanDefinitions(mapperScanAttrs, registry);
    }
  }
}复制代码

3.3 ImportSelector

不少想Springboot starter中要开启某个功能时就会用到ImportSelector,好比像开启服务注册与发现的注解@EnableDiscoveryClient,主要原理是ImportSelector中的selectImports方法会返回一个字符串的数组,这里的字符串其实是一个个咱们须要注册类的全路径,相似于com.xjw.entity.pojo.MessageRecord,Spring会根据全路径反射生成Bean。源码这一块就先不讲了(手动狗头)。框架

public class CommonModelSelector implements ImportSelector {public CommonModelSelector() {
    }public String[] selectImports(AnnotationMetadata annotationMetadata) {return new String[]{MessageRecord.class.getName()};
    }
}复制代码

4 FactoryBean

FactoryBean是一个特殊的Bean,是否不少好哥哥在面试时被问到过FactoryBean和BeanFactry的区别呢,说道这个个人眼眶湿润了(讲道理,这个在面所谓高级工程师的时候常常被问到)。FactoryBean是一个特殊Bean,当咱们实现这个接口时,会生成两个Bean对象,第一个就是实现类自己,须要用在Bean名称前(正常是类名首字母小写)加&来获取Bean,第二个Bean的话实际上就是getObject方法返回的bean,须要注意的是这种方式须要配合@Component或者@Configuration来实现。BeanFactry简单点来讲就是Spring上下文的容器。
湿了ide

实例代码以下:rest

@Componentpublic class FactoryBeanLearn implements FactoryBean {@Overridepublic Object getObject() throws Exception {//这个Bean是咱们本身new的,这里咱们就能够控制Bean的建立过程了return new MessageRecord();
    }	/**
	 * bean的类型
	 *
	 **/@Overridepublic Class<?> getObjectType() {return MessageRecord.class;
    }	/**
	 * 是不是单例的
	 *
	 **/@Overridepublic boolean isSingleton() {return true;
    }
}复制代码