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;
  }
}