spring ioc中如何在默认单例下使用多例

 

还是在项目中遇到的场景,本来是个excel工具类,但是需要校验表中的数据,还有必要的全局变量,就必须把这个工具类弄成一个多例bean了。

但是我们知道,在日常使用spring时,将bean注入ioc容器时,默认都是以单例注入,除非注明为多例。一个接口用

@Controller注解时往往都是单例。那么如果在这种情况下使用多例bean呢?

1.在单例bean(spring中单例注入),不能使用@Resource,@Autowired直接获取多例bean

(以下是错误代码!)

Api(tags = "组织管理相关")
@RestController
@RequestMapping("/user/sys-user")
public class SysUserController {

    @Autowired
    SysUserExcelImport SysUserExcelImport;

    @Resource
    SysUserExcelImport SysUserExcelImport;

    
@PostMapping("/saveExcel")
    @ApiOperation(value = "1.基础用户管理_excel导入基础用户信息", notes = "")
    public ResponseBean saveExcel(@RequestParam(value = "files") MultipartFile[] files,@RequestParam(value = "roleIds",required = false)List<String> roleIds) {

        try {
            for (MultipartFile multipartFile : files) {
                File file = MultipartFileToFileUtil.multipartFileToFileLocal(multipartFile);
                try {
                    //如果直接通过注解获取,再打印SysUserExcelImport的hashcode值会发现都会一样
                    SysUserExcelImport.postConstruct(file);
                    
                    sysUserExcelImport.close();
                    file.delete();
                    if(sysUserExcelImport.getError()){
                        return new ResponseBean(false,sysUserExcelImport.getErrorExcelPath(),OrganizationEnums.ORGANIZATION_SAVE_USER_EXCEL_FAIL);
                    }else{
                        sysUserService.saveUsers(sysUserExcelImport.getSaveSysUserBeans(),roleIds);
                        return new ResponseBean(true, OrganizationEnums.ORGANIZATION_SAVE_USER_EXCEL_SUCCESS);
                    }
                }catch (Exception e){
                    file.delete();
                    throw  e;
                }
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseBean(false, e.getMessage(), OrganizationEnums.ORGANIZATION_SAVE_USER_EXCEL_FAIL);
        }
    }

}

spring容器中在加载controller时同时也会初始化@Resource和@Autowired注解的全局变量,并且只会初始化一次。初始化一次的结果就是这个工具类不会再次出现一个实例对象,并且不能实现多例。(讲的太笼统,可以去看看看看spring在启动时ioc加载bean的过程就清楚了)。

如果不能作为全局变量,那么唯一的解决办法只能通过spring的bean工厂获取了

2.spring提供了 ApplicationContextAware接口以获取上下文环境,再通过上下文环境获取bean

public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if(SpringUtils.applicationContext == null){
            SpringUtils.applicationContext  = applicationContext;
        }
    }

    
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }


    public static String[] controllersBeanNames(Class<? extends Annotation>  clazz){
        return getApplicationContext().getBeanNamesForAnnotation(clazz);
    }

    public static Map<String, Object> controllersBeans(Class<? extends Annotation>  clazz){
        return getApplicationContext().getBeansWithAnnotation(clazz);
    }

    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }

    public static <T> T getBean(Class<T> requiredType) {
        return applicationContext.getBean(requiredType);
    }

    public static <T> T getBean(String name, Class<T> requiredType) {
        return applicationContext.getBean(name, requiredType);
    }

    public static boolean containsBean(String name) {
        return applicationContext.containsBean(name);
    }

    public static boolean isSingleton(String name) {
        return applicationContext.isSingleton(name);
    }

    public static Class<? extends Object> getType(String name) {
        return applicationContext.getType(name);
    }

}

这个地方是我写错了。原谅我,,,,,, 

@PostMapping("/saveExcel")
    @ApiOperation(value = "1.基础用户管理_excel导入基础用户信息", notes = "")
    public ResponseBean saveExcel(@RequestParam(value = "files") MultipartFile[] files,@RequestParam(value = "roleIds",required = false)List<String> roleIds) {
        //获取bean
        SysUserExcelImport sysUserExcelImport=SpringUtils.getBean(SysUserExcelImport.class);
        
        try {
            for (MultipartFile multipartFile : files) {
                File file = MultipartFileToFileUtil.multipartFileToFileLocal(multipartFile);
                try {
                    sysUserExcelImport.postConstruct(file);
                    sysUserExcelImport.close();
                    file.delete();
                    if(sysUserExcelImport.getError()){
                        return new ResponseBean(false,sysUserExcelImport.getErrorExcelPath(),OrganizationEnums.ORGANIZATION_SAVE_USER_EXCEL_FAIL);
                    }else{
                        sysUserService.saveUsers(sysUserExcelImport.getSaveSysUserBeans(),roleIds);
                        return new ResponseBean(true, OrganizationEnums.ORGANIZATION_SAVE_USER_EXCEL_SUCCESS);
                    }
                }catch (Exception e){
                    file.delete();
                    throw  e;
                }
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseBean(false, e.getMessage(), OrganizationEnums.ORGANIZATION_SAVE_USER_EXCEL_FAIL);
        }
    }

这里需要注意的是如果通过bean名称来获取,但是没有获取到。我一直以为是在多例的情况下不会主动加载,,但是发现我错了。。其实是name不对。推荐下这篇文章https://blog.csdn.net/qq_22651103/article/details/88727712。通过注解name默认的是啥,,其实通过name获取也是可以的,但是要写对

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值