在普通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】```