Springboot使用@Autowire注解时,通过注解读到的对象是null

在SpringBoot项目中遇到非Controller类的bean注入失败的问题,尝试了将工具类声明为Spring组件、使用@PostConstruct注解以及调整注入对象的访问权限等方法均未解决问题。最终通过实现ApplicationContextAware接口,从ApplicationContext中动态获取bean得以解决。

背景:
项目使用SpringBoot框架,在非Controller类中注入bean,发现bean为空,也就是按照原来controller层通过@Autowired注入service层失效。

踩的坑:
测试百度出来的前三页帮助,没有成功。包括:
(1)将工具类申明为spring组件,如 @Autowire,@Compent 等,在spring自动扫描包设置中将工具类所在的包加进来;不行
(2)通过注解@PostConstruct,也就是博客https://blog.youkuaiyun.com/georgeshaw1/article/details/74943089 记录的,不行;
(3)修改注入对象作用域的级别private–>public或protected,不行

解决方法:
写了个spring工具类实现ApplicationContextAware接口,从applicationContext中获取,通过其中的静态方法获取想要的bean。
具体就参考代码吧:

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

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

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }

    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz){
        return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name,Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }

}
在Spring Boot中,Controller无法通过`@Autowired`正确注入Service对象导致对象为空的问题,通常是由Spring容器未正确管理Bean或Bean注入流程中的配置问题引起的。以下是具体的解决方案和原因分析: ### 1. 确保Service实现类添加了`@Service`注解 `@Service`是Spring框架中专门用于标注业务逻辑层的组件,只有添加了该注解,Spring才能将其识别为Bean并纳入IoC容器管理。若Service实现类缺少`@Service`注解,Controller层通过`@Autowired`注入会失败,导致对象为`null`。示例代码如下: ```java @Service public class UserServiceImpl implements UserService { // 业务逻辑 } ``` ### 2. 确保Controller类本身被Spring管理 Controller类需要使用`@RestController`或`@Controller`注解,这样Spring才能将其识别为一个控制器并进行管理。如果Controller类未添加这些注解,则无法通过`@Autowired`注入其他Bean。 ```java @RestController public class UserController { @Autowired private UserService userService; } ``` ### 3. 确保启动类扫描到Controller和Service所在的包 Spring Boot默认会扫描主启动类所在包及其子包下的组件。如果Controller或Service所在的包不在扫描范围内,可以通过`@ComponentScan`注解显式指定需要扫描的包。 ```java @SpringBootApplication @ComponentScan(basePackages = {"com.example.controller", "com.example.service"}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` ### 4. 使用`@PostConstruct`初始化对象 在某些情况下,即使通过`@Autowired`注入了Service对象,但在某些初始化逻辑中可能还未完成注入。可以通过`@PostConstruct`注解的方法在Bean初始化完成后执行相关操作,确保对象已经注入。 ```java @RestController public class TestController { @Autowired private TestService testService; private TestService localTestService; @PostConstruct public void init() { localTestService = testService; } @GetMapping("/test") public void testMethod() { localTestService.doSomething(); // 使用初始化后的对象 } } ``` ### 5. 检查Bean的作用域和依赖关系 如果Service Bean的作用域配置错误(例如设置为`prototype`),或者存在依赖关系未正确解析,也可能导致注入失败。确保Service Bean的作用域和依赖关系配置正确。 ### 6. 使用`@Autowired(required = false)`避免注入失败抛出异常 当注入的Bean可能不存在,可以将`@Autowired`的`required`属性设置为`false`,这样即使找不到匹配的Bean也不会抛出异常。 ```java @Autowired(required = false) private TestService testService; ``` ### 7. 避免直接通过`new`关键字创建对象 如果在Controller中通过`new`关键字手动创建Service对象,而不是通过Spring注入,那么该对象将不会被Spring管理,导致注入失败。应始终通过`@Autowired`注入依赖对象。 ### 8. 检查Bean的加载顺序 在某些复杂场景中,Bean的加载顺序可能导致注入失败。可以通过`@DependsOn`注解显式指定Bean的依赖关系,确保正确的加载顺序。 ```java @Service @DependsOn("anotherService") public class TestService { // 依赖anotherService } ``` ### 9. 使用`ApplicationContext`手动获取Bean 在某些特殊场景下,例如工具类或定任务中,可以通过`ApplicationContext`手动获取Bean,确保获取对象由Spring管理。 ```java @Component public class SpringContextUtil implements ApplicationContextAware { private static ApplicationContext context; @Override public void setApplicationContext(ApplicationContext applicationContext) { context = applicationContext; } public static <T> T getBean(Class<T> beanClass) { return context.getBean(beanClass); } } ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值