1.装配bean的三种方式:@Autowired、@Resource、final 修饰成员变量后构造方法注入
(1)提供方不同
@Autowired 是Spring提供的,@Resource 是J2EE提供的,final 方式是spring-boot官方建议的
(2)装配时默认类型不同
@Autowired只按type装配,@Resource默认是按name装配。构造方法注入默认是按照name方式
(3)使用区别
(1)@Autowired与@Resource都可以用来装配bean,都可以写在字段或setter方法上
(2)@Autowired默认按类型装配,默认情况下必须要求依赖对象存在,如果要允许null值,可以设置它的required属性为false。如果想使用名称装配可以结合@Qualifier注解进行使用。
(3)@Resource,默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行名称查找。如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
@Resource(name=“beanName”)=Resource
(4)Springboot官方建议使用final来修饰成员变量,然后通过构造方法来进行注入原因:final修饰的成员变量是不能够被修改的,反射那就没办法了。注解生成构造方式建议使用@RequiredArgsConstructor,原因如下:
@NoArgsConstructor后会 生成无参的构造方法
@RequiredArgsConstructor 会将类的每一个final字段或者non-null字段生成一个构造方法
@AllArgsConstructor 生成一个包含过所有字段的构造方法。
使用@AllArgsConstructor后,@Value会失效,获取不到值。使用@RequiredArgsConstructor则正常。今后注入service、mapper等都使用@RequiredArgsConstructor好了。
2. spring mvc 项目中当@autowired注解注入失败的时候,可以使用下面的方式实现bean的注入:
XfUserTodoServiceImpl xfUserTodoService = (XfUserTodoServiceImpl) ContextLoader.getCurrentWebApplicationContext().getBean("xfUserTodoServiceImpl");
使用场景:比如使用websocket的时候,就会有这样的需求,当连接成功的时候,需要执行业务方法的时候,就有注入的需求,然而@autowired是无效的,所有就会用到上面的方法。
注意事项:getBean() 方法的参数是类名首字母小写。
3.spring之ApplicationContextAware详解
(1) 文章参考 spring之ApplicationContextAware详解 - 简书
@Service("gatewayService")
public class GatewayServiceImpl implements IGatewayService,ApplicationContextAware {
private Logger logger= LoggerFactory.getLogger(getClass());
Map<ServiceBeanEnum,IGatewayBo> chargeHandlerMap=new HashMap<ServiceBeanEnum,IGatewayBo>();
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext=applicationContext;
}
}
(2) 当一个接口需要被spring容器管理时(MsgGateway 是一个接口)
@MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
public interface MsgGateway {
void publish(@Header(MqttHeaders.TOPIC) String topic, Object data);
}
将MsgGateway 注入spring 容器
@Component
public class MqttProducerContext implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (MqttProducerContext.applicationContext == null) {
MqttProducerContext.applicationContext = applicationContext;
}
}
public static MsgGateway getGateway() {
return applicationContext.getBean(MsgGateway.class);
}
}
调用MsgGateway
public class MessageOperator {
private static final Logger logger = LoggerFactory.getLogger(MessageOperator.class);
private static MessageOperator instance = new MessageOperator();
public static MessageOperator getInstance() {
return instance;
}
/**
* publish: publish topic
* @since JDK 1.8
*/
public boolean publish(String topic, String message) {
try {
MqttProducerContext.getGateway().publish(topic, message);
} catch (Exception e) {
logger.info("Error when sending " + e);
return false;
}
return true;
}
}