「面试」能说说Spring除了@Service注册Bean之外还有其他方式吗

前言

众所周知,在我们平时的开发中,Spring这个框架已经环绕了整个项目,不是说我们不能不用Spring,而是这样做的代价太大了。每次面试,总是会问道Spring IOC、AOP、事务…,每每到这,我总是留下了悔恨的泪水。今天我的眼眶又湿润了…,咳咳咳,风有点大,进沙子了
太难了

正题

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

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

@Component
public class ApproveCenterServiceImpl implements ApproveCenterService {
    
    
}
@Service
public class ApproveCenterServiceImpl implements ApproveCenterService {
    
    
}
@Repository
public class ApproveCenterServiceImpl implements ApproveCenterService {
    
    
}
2.@Bean和@Configuration

这种方式是不是很熟悉,常用于标注配置类,最简单的一个例子就是我们使用SpringBoot 的时候需要手动注册一个Bean叫做RestTemplate

@Configuration
public class RestTemplateConfig {
    
    
    
    @Bean
    public RestTemplate restTemplate() {
    
    
        return new RestTemplate();
    }
}
3.使用@Import

@Import 注解可以注册三种类型的Bean,第一种就是普通类,第二种DefinitionRegistrar类,第三种就是ImportSelector

3.1.普通类:

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

3.2.DefinitionRegistrar

实现了ImportBeanDefinitionRegistrar,这种方式在实现类中提供了一个注册器,有一个大家很熟悉的注解(@MapperScan)大家点进去看看就明白了

@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上下文的容器
在这里插入图片描述

@Component
public class FactoryBeanLearn implements FactoryBean {
    
    

    @Override
    public Object getObject() throws Exception {
    
    
        //这个Bean是我们自己new的,这里我们就可以控制Bean的创建过程了
        return new MessageRecord();
    }

	/**
	 * bean的类型
	 *
	 **/
    @Override
    public Class<?> getObjectType() {
    
    
        return MessageRecord.class;
    }

	/**
	 * 是否是单例的
	 *
	 **/
    @Override
    public boolean isSingleton() {
    
    
        return true;
    }
}

未完待续…

本期到这里啦,写的不对的地方巨佬们多多指点,喜欢的话来一个一键三连吧

猜你喜欢

转载自blog.csdn.net/qq_34090008/article/details/110474631