@Component和@Bean和@Autowired之间的区别

@Component(@Controller、@Service、@Repository):自动创建一个实例并装配到Spring容器中(放到IOC中)
【Ps.写好的其他项目jar放到pom,Spring自动装配,简单好用,简直冒了泡了】

@Bean :手动创建一个实例,并保留在IOC中。
@Bean的好处:麻烦一点,但自定义性更强。当我们引用第三方库中的类需要装配到Spring容器时,则只能通过@Bean来实现~(因为你并不能改他的源代码在他类上加个@Component ,所以只能这么玩了。
引申:代码回调函数也是起这个作用)

@SpringBootApplication
public class Application {

    @Bean
    BookingService bookingService() {
        return new BookingService();
    }

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
        BookingService bookingService = ctx.getBean(BookingService.class);
        bookingService.book("Alice", "Bob", "Carol");
    }
}

@Autowired:织入(Spring上下文已有实例(已注入IOC),@Autowired只是取一下)
@Autowired说“请给我一个该类的实例,例如,我之前用@Bean注释创建的一个实例进入IOC了”。

@Autowired一般用在变量上,spring容器会自动注入值。

如果用在方法上:

@Autowired(required = false)
public void setRedisTemplate(RedisTemplate redisTemplate) {
    RedisSerializer stringSerializer = new StringRedisSerializer();
    redisTemplate.setKeySerializer(stringSerializer);
    redisTemplate.setValueSerializer(stringSerializer);
    redisTemplate.setHashKeySerializer(stringSerializer);
    redisTemplate.setHashValueSerializer(stringSerializer);
    this.redisTemplate = redisTemplate;
}
spring容器会在类加载后自动注入这个方法的参数,并执行一遍方法。

总结: @Autowired注解作用在方法上
(1)该方法如果有参数,会使用autowired的方式在容器中查找是否有该参数
(2)会执行该方法
 (3)这就像static{}块语句会初始化执行,但顺序不一样(static{}比↑快)。

实际项目一般是@Component配合@Autowired联用
但是改成这样玩也行:

@SpringBootApplication
public class Application {

  @Autowired
  BookingService bookingService;

  @Bean
  BookingService bookingService() {
    return new BookingService();
  }

  public static void main(String[] args) {
    bookingService.book("Alice", "Bob", "Carol");
  }
}

在这种情况下,@Bean注释为Spring提供了BookingService,并加以@Autowired利用。但这是一个毫无意义的示例,因为你都在同一个类中使用它们…不如下面就直接new对象呢还能少写上面那几行呢。
但是如果你在一个类中@Bean定义对象实例(注册到IOC),而在另一个类中@Autowired使用。那@Bean+@Autowired就变得很有用。

补充阅读
@Configuration和@Component区别


最近知道: A注解上面有几个注解,其他地方用到这个A注解,会是叠加效果~那么,这就又可以(借助注解)抽象一层了(不过注解本质就是接口啊,所以,能实现抽象抽取的效果,好像也是理所当然的哈_
例如,下面的oaScenePeopleHandlers能自动注入

   private Map<String, OaScenePeopleHandler> oaScenePeopleHandleMap;

    @Autowired
    public void setOaScenePeopleHandleMap(List<OaScenePeopleHandler> oaScenePeopleHandlers) {
        // 注入各种场景类型的处理类
        oaScenePeopleHandleMap = oaScenePeopleHandlers.stream().collect(
                Collectors.toMap(orderHandler -> AnnotationUtils.findAnnotation(orderHandler.getClass(), OaScenePeopleHandlerType.class).sceneType(),
                        v -> v, (v1, v2) -> v1));
    }

是因为

public interface OaScenePeopleHandler {

    void sendSecnePeoplePermissionHandle(OaScenePeopleEntity oaScenePeopleEntity);
}
@OaScenePeopleHandlerType(sceneType="1")
public class ChangJingHandler implements OaScenePeopleHandler {
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service  
public @interface OaScenePeopleHandlerType {
    // 1.场景   2.设备
    String sceneType();
}

破案了,@Service出现了,原来在这呢。
如果注掉了就会报错了
@Component和@Bean和@Autowired之间的区别_第1张图片
以后有空可以把上述代码用@Bean重写一遍玩玩(这不找麻烦呢不是,故意变复杂)。

Ps.
能用@Autowired等注解有个另外的隐藏前提(除了织入的类本身得有先注入到IOC):被写这些注解代码的这个类,也得教给了IOC(Spring管理),才能里面写了这些注解,这些注解会被扫描(?会有意义?),否则报空指针异常
如:

     @Autowired
    private WeChatSendMsgUtils weChatSendMsgUtils;
    
     @Test
    public void testSendWx2(){

        String templateId=systemProperties.getExamineConfirm();
        String url="www.baidu.com";
        //我的测试号
        String toUserWxId="oLh_dvztrOLfkDm5RJ6F_ngBgByQ";
        //2020年6月30日 考虑思路:sendWxMsg可以是静态方法不好用,但那么wxMpService注入也得静态的。WeChatSendMsgUtils 得交给Spring。或者  new WeChatSendMsgUtils().sendWxMsg也行【但是weChatSendMsgUtils内容里有注解,所以该类本身也得交给IOC才能里面的注解有意义,那么,既然该类也交给IOC,我何不也用Spring注入呢,所以,这里没用new。那么,静态也没啥更方便了,所以静态又没有用】
        weChatSendMsgUtils.sendWxMsg(
                templateId,
                url,
                toUserWxId,
                new WxMsgDto("AA的随行BB接受了访客邀请!",
                        "普普",
                        "面试",
                        "2019-01-02 9:00 - 2019-01-02 9:00",
                        "1666666666",
                        "更多信息,请点击详情进行查看"));
    }

@Component
public class WeChatSendMsgUtils {

    @Resource
    private WxMpService wxMpService;

    /**
     * 只支持三行或四行的微信模板
     * @param templateId 模板id
     * @param url  跳转url
     * @param toUserWxId  目标wxId
     * @param wxMsgDto   信息数组/集合
     */
    public  void sendWxMsg(String templateId, String url, String toUserWxId, WxMsgDto wxMsgDto) {
     try {
            msg = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);

如果WeChatSendMsgUtils.java不加@Component(或者@Service…),那么 @Resource
private WxMpService wxMpService; 会是无效的,使用时会是空的。(可能是里面的注解会无意义,Spring会不扫描吧)

代码里黏贴出来: //2020年6月30日 考虑思路:sendWxMsg可以是静态方法不好用,但那么wxMpService注入也得静态的。WeChatSendMsgUtils 得交给Spring。或者 new WeChatSendMsgUtils().sendWxMsg也行【但是weChatSendMsgUtils内容里有注解,所以该类本身(“包住这些注解的那个类”,它没交给Spring,那么里面的东西也没交给Spring,感觉挺有这道理的[可以理解成“没扫描”吗]【他(本身)也得注入,他里面的注入(里面注解的效果)才能顺带这一起注入。他被交给Spring管理,他才能有从Spring取东西的资格?/能力?/权利?/权力?】)也得交给IOC才能里面的注解有意义,那么,既然该类也交给IOC,我何不也用Spring注入呢,所以,这里没用new 干脆全用Spring管理。那么,静态也没啥更方便了,所以静态又没有用的必要】

Ps.某注解定义时,上面放注解,那么用该某注解时,是会有叠加效果的(上文说过了。。。“叠加作用/叠加效果,可以理解成接口的多继承”)。(参见springboot启动项。和我的有道笔记策略模式破案了。)

--------一次实践2020年7月6日

@Component
public class WechatAccount {

    @Autowired
    private static   WeChatAccountConfig weChatAccountConfig ;

    //(测试、正式)公众号
    public  String APPID = weChatAccountConfig.getAppId();
    public  String APPSECRET = weChatAccountConfig.getAppSecret();
    public  String TOKEN = weChatAccountConfig.getToken();
    public  String ENCODINGAESKEY =weChatAccountConfig.getAesKey();
}

报错:加载时null(应该是weChatAccountConfig 对象null了)
尝试解析/解读/分析:因为有加载顺序,全局静态变量应该快于方法吧,所以报空。
解决尝试:

@Component
public class WechatAccount {

    //@Autowired
   // private static   WeChatAccountConfig weChatAccountConfig ;

    //(测试、正式)公众号
    public static  String APPID;
    public static  String APPSECRET;
    public static  String TOKEN;
    public static  String ENCODINGAESKEY;

    @Autowired
    public  void  initWechatAccount(WeChatAccountConfig weChatAccountConfig){
        APPID = weChatAccountConfig.getAppId();
        System.out.println("hhhhhh"+APPID);
        APPSECRET = weChatAccountConfig.getAppSecret();
        TOKEN = weChatAccountConfig.getToken();
        ENCODINGAESKEY =weChatAccountConfig.getAesKey();
    }
}

@Component和@Bean和@Autowired之间的区别_第2张图片

你可能感兴趣的:(工作IT)