一个普通JAVA类无法使用@Autowired等注解注入一个bean

在普通Java类中注入bean,普通Java类中用@Autowired等注解是无法注入bean的

验证

准备需要被注入的bean,使用@Service注解(@Component等注解均可)

package com.halon;

import org.springframework.stereotype.Service;

/**
 * @Author halon
 * @create 2021/9
 */
@Service
public class TestService {
    public void serviceTest(){
        System.out.println("serviceTest Running ....");
    }
}

准备一个普通的JAVA对象

package com.halon;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @Author halon
 * @create 2021/9
 */
public class TestEntity {
    private final Logger LOGGER = LoggerFactory.getLogger(TestEntity.class);
    @Autowired
    private TestService testService;

    public void setTestService() {
        try {
            testService.serviceTest();
            LOGGER.info("【Autowired SUCCESS】");
        } catch (NullPointerException e) {
            LOGGER.warn("【Autowired ERROR】");
        }
    }
}

写一个Controller测试一哈

package com.halon;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author halon
 * @create 2021/9
 */
@RestController
public class TestController {

    @PostMapping("/post")
    public void testController() {
        TestEntity testEntity = new TestEntity();
        testEntity.setTestService();
    }
}

请求

POST localhost:8080/post

控制台输出

 WARN 8412 --- [nio-8080-exec-1] com.halon.TestEntity                     :Autowired ERROR】

在普通Java类中注入bean,普通Java类中用@Autowired是无法注入bean的。
如果在普通的JAVA类上加上@Component注解会发生什么呢?

改变

@Component
public class TestEntity {
...

控制台输出:

 WARN 8412 --- [nio-8080-exec-1] com.halon.TestEntity                     :Autowired ERROR】

为什么会出现这种情况呢?
原因是在controller层中使用的是new创建一个对象,并不是通过Spring创建一个bean,这样就不能走完整的SpringBean的生命周期也没有办法实现AOP导致即使在普通的JAVA类上加了@Component注解使Spring扫描带该类但是仍然无法在Controller层通过new创建对象使普通JAVA类中的注解生效。

解决方法:

1.在controller 层通过注解注入加了@Component注解普通JAVA类

在上述的基础上修改controller层的代码如下:

package com.halon;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author halon
 * @create 2021/9
 */
@RestController
public class TestController {
    @Autowired
    private TestEntity testEntity;

    @PostMapping("/post")
    public void testController() {
//        TestEntity testEntity = new TestEntity();
        testEntity.setTestService();
    }
}

发起请求后控制台输出结果

serviceTest Running ....
INFO 6704 --- [nio-8080-exec-1] com.halon.TestEntity                     :Autowired SUCCESS】

如果我就是不想在普通的JAVA类中加上@Component注解,但还是想在普通JAVA类中使用Spring扫描到的Bean怎么办?

2.实现ApplicationContextAware接口

实现ApplicationContextAware接口,并加入Component注解,让spring扫描到该bean,用于在普通Java类中注入bean。(普通Java类中用@Autowired是无法注入bean)

创建一个工具类

package com.halon.util;

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


/**
 * @Author halon
 * @create 2021/9
 */
@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.
     *
     * @param name
     * @return
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

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

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

修改普通JAVA类代码如下:

package com.halon;

import com.halon.util.SpringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @Author halon
 * @create 2021/9
 */
public class TestEntity {
    private final Logger LOGGER = LoggerFactory.getLogger(TestEntity.class);
    @Autowired
    private TestService testService;

    public void setTestService() {
        try {
            testService.serviceTest();
            LOGGER.info("【Autowired SUCCESS】");
        } catch (NullPointerException e) {
            LOGGER.warn("【Autowired ERROR】");
            try {
                SpringUtil.getBean(TestService.class).serviceTest();
                LOGGER.info("【getBean SUCCESS】");
            } catch (Exception exception) {
                LOGGER.warn("【getBean ERROR】");
            }
        }
    }
}

controller代码

@RestController
public class TestController {

    @PostMapping("/post")
    public void testController() {
        TestEntity testEntity = new TestEntity();
        testEntity.setTestService();
    }
}

发起请求,控制台输出结果

WARN 23500 --- [nio-8080-exec-1] com.halon.TestEntity                     :Autowired ERROR】
serviceTest Running ....
INFO 23500 --- [nio-8080-exec-1] com.halon.TestEntity                     : 【getBean SUCCESS】```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值