众所周知,在咱们平时的开发中,Spring这个框架已经环绕了整个项目,不是说咱们不能不用Spring,而是这样作的代价太大了。每次面试,老是会问道Spring IOC、AOP、事务等等,今天这篇的话是猛男我刚工做碰到的一个面试真题,可怜我那时只知道@Service。而后就回去等通知了,到如今尚未给我通知。面试
另外的话,今天这篇会讲几种注入方式,至于原理好哥哥们就先别想了(别打我脸就行),这随便拿一个出来都的讲源码讲一遍,主要须要依赖的东西优势多,因此找个机会将Spring IOC 那一块的源码弄出来讲说,这一篇的话主要是讲个大概。
spring
这种方式就很简单,像@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 { }复制代码
这种方式是否是很熟悉,经常使用于标注配置类,最简单的一个例子就是咱们使用SpringBoot 的时候须要手动注册一个Bean``叫作RestTemplate`spring-mvc
@Configurationpublic class RestTemplateConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate(); } }复制代码
@Import 注解能够注册三种类型的Bean,第一种就是普通类,第二种DefinitionRegistrar类,第三种就是ImportSelectormvc
/** * @author xiejianwei */@Import(MessageRecord.class)public @interface ImportBean { }复制代码
实现了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); } } }复制代码
不少想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()}; } }复制代码
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; } }复制代码