范文健康探索娱乐情感热点
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

新年涨新知!基于注解的Spring容器配置

  写在前面
  Spring容器支持3种方式进行bean定义信息的配置,现在具体说明下: XML:bean的定义和依赖都在xml文件中配置,比较繁杂。 Annotation-based :通过直接的方式注入依赖,xml文件配置扫描包路径,xml简化很多。 Java-based: 通过配置类和注解批量扫描和注册bean,不再需要xml文件。
  前面的案例都是基于XML的,这篇介绍Annotation-based方式。 本文内容通过简单案例入门基于注解方式的容器配置使用 Autowired  的详细使用,配合@Primary  、@Qulifier  案例入门1
  该入门案例的bean的定义信息在xml文件这个,使用注解来进行依赖注入。
  @Autowired  :将构造函数、字段、设置方法或配置方法标记为由 Spring 的依赖注入工具自动装配。定义类并通过@Autowird注入依赖public class BeanOne { }  public class BeanTwo {     // 注解注入 BeanOne     @Autowired     private BeanOne beanOne;      @Override     public String toString() {         return "BeanTwo{" +                 "beanOne=" + beanOne +                 "}";     } } xml文件启用注解配置<?xml version="1.0" encoding="UTF-8"?>                                                获取容器中的bean进行使用@org.junit.Test public void test_annotation_config() {         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo06/spring2.xml");         BeanTwo beanTwo = context.getBean(BeanTwo.class);         System.out.println(beanTwo);         context.close();     }      // 输出 BeanTwo{beanOne=com.crab.spring.ioc.demo06.BeanOne@491666ad} 案例入门2
  入门案例1中简化传统的xml配置依赖注入的方式,但是bean的定义信息依旧是需要手动配置在xml中的。可以扫描bean的方式进一步简化,增加配置节即可。  通过注解标记类为bean
  @Component  :表示带注释的类是"组件"。在使用基于注释的配置和类路径扫描时,此类被视为自动检测的候选对象@Component public class RepositoryA implements RepositoryBase { } @Component public class RepositoryB  implements RepositoryBase { }  @Component public class ServiceA {     @Autowired     private RepositoryA repositoryA;      @Autowired     private RepositoryB repositoryB;    	     // 省略 Getter toString() } xml配置扫描包路径
  xml配置文件,非常简洁 <?xml version="1.0" encoding="UTF-8"?>                         获取容器中bean使用
  测试程序和上一篇的类似。 package com.crab.spring.ioc.demo06;  /**  * @author zfd  * @version v1.0  * @date 2022/1/13 15:11  * @关于我 请关注公众号 螃蟹的Java笔记 获取更多技术系列  */ public class Test {      @org.junit.Test     public void test() {         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo06/spring1.xml");         ServiceA serviceA = context.getBean(ServiceA.class);         RepositoryA repositoryA = context.getBean(RepositoryA.class);         RepositoryB repositoryB = context.getBean(RepositoryB.class);         System.out.println(serviceA);         System.out.println(serviceA.getRepositoryA() == repositoryA);         System.out.println(serviceA.getRepositoryB() == repositoryB);         context.close();     } }
  运行结果 ServiceA{repositoryA=com.crab.spring.ioc.demo06.RepositoryA@27c86f2d, repositoryB=com.crab.spring.ioc.demo06.RepositoryB@197d671} true true
  结论: RepositoryA  、RepositoryB  、ServiceA   都扫描到容器中管理,ServiceA  的依赖已经自动DI了。相比传统的XML方式,这种方式简洁省心不少。
  注意:XML方式和注解配置方式可以混合用。注解注入在 XML 注入之前执行。因此,XML 配置会覆盖注解方式注入的。 @Required使用
  @Required 注解适用于 bean 属性设置方法,如果容器这个没有对应的bean则会抛出异常。public class SimpleMovieLister {      private MovieFinder movieFinder;      @Required     public void setMovieFinder(MovieFinder movieFinder) {         this.movieFinder = movieFinder;     } }
  @Required 注解和 RequiredAnnotationBeanPostProcessor   从 Spring Framework 5.1 开始正式弃用,更好的方式是使用构造函数注入(或 InitializingBean.afterPropertiesSet() 的自定义实现或自定义 @PostConstruct 方法以及 bean 属性设置器方法)。@Autowired使用
  将构造函数、字段、Setter  方法或配置方法标记为由 Spring 的依赖注入工具自动装配, required  指定是否必须。这是 JSR-330 @Inject注解的替代方案。标记在构造函数、字段、Setter方法上
  来一个综合3种注解位置的类@Component public class Service1 {     private RepositoryA repositoryA;     private RepositoryB repositoryB;     // 标记field     @Autowired     private RepositoryC repositoryC;      // 标记构造函数     @Autowired     public Service1(RepositoryA repositoryA) {         this.repositoryA = repositoryA;     }      @Autowired     public void setRepositoryB(RepositoryB repositoryB) {         this.repositoryB = repositoryB;     }      @Override     public String toString() {         return "Service1{" +                 "repositoryA=" + repositoryA +                 ", repositoryB=" + repositoryB +                 ", repositoryC=" + repositoryC +                 "}";     } }
  测试方法和结果如下    @org.junit.Test     public void test_autowired() {         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo06/spring1.xml");         Service1 bean = context.getBean(Service1.class);         System.out.println(bean);         context.close();     }  // 结果 Service1{repositoryA=com.crab.spring.ioc.demo06.RepositoryA@79efed2d, repositoryB=com.crab.spring.ioc.demo06.RepositoryB@2928854b, repositoryC=com.crab.spring.ioc.demo06.RepositoryC@27ae2fd0}
  从输出结果来看,三种位置注入依赖都是可以的。
  从 Spring Framework 4.3 开始,如果目标 bean 仅定义一个构造函数,则不再需要在此类构造函数上使用 @Autowired 注释。 @Autowired注入集合默认顺序
  容器中所有符合类型的都会自动注入,默认顺序是bean注册定义的顺序。/**  * @author zfd  * @version v1.0  * @date 2022/1/15 17:48  * @关于我 请关注公众号 螃蟹的Java笔记 获取更多技术系列  */ @Component public class Service2 {     @Autowired     private List repositoryList;     @Autowired     private Set repositorySet;     @Autowired     private RepositoryBase[] repositoryArr;          // 省略 Getter和Setter }
  测试和结果    @org.junit.Test     public void test_collection() {         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo06/spring1.xml");         Service2 service2 = context.getBean(Service2.class);         System.out.println(service2.getRepositoryList());         System.out.println(service2.getRepositorySet());         Arrays.stream(service2.getRepositoryArr()).forEach(System.out::println);         context.close();     } [com.crab.spring.ioc.demo06.RepositoryA@2ddc8ecb, com.crab.spring.ioc.demo06.RepositoryB@229d10bd, com.crab.spring.ioc.demo06.RepositoryC@47542153] [com.crab.spring.ioc.demo06.RepositoryA@2ddc8ecb, com.crab.spring.ioc.demo06.RepositoryB@229d10bd, com.crab.spring.ioc.demo06.RepositoryC@47542153] com.crab.spring.ioc.demo06.RepositoryA@2ddc8ecb com.crab.spring.ioc.demo06.RepositoryB@229d10bd com.crab.spring.ioc.demo06.RepositoryC@47542153
  从结果看,顺序是ABC。通过@Ordered指定顺序
  在RepositoryA   RepositoryB   RepositoryC  上加上@Ordered  ,数值越小优先级越高。@Component @Order(0) // 指定注入集合时的顺序 public class RepositoryA implements RepositoryBase { }  @Component @Order(-1) public class RepositoryB  implements RepositoryBase { }  @Component @Order(-2) public class RepositoryC implements RepositoryBase{ }
  还是运行上面的测试test_collection  ,观察输出顺序。[com.crab.spring.ioc.demo06.RepositoryC@56a6d5a6, com.crab.spring.ioc.demo06.RepositoryB@309e345f, com.crab.spring.ioc.demo06.RepositoryA@7a4ccb53] [com.crab.spring.ioc.demo06.RepositoryA@7a4ccb53, com.crab.spring.ioc.demo06.RepositoryB@309e345f, com.crab.spring.ioc.demo06.RepositoryC@56a6d5a6] com.crab.spring.ioc.demo06.RepositoryC@56a6d5a6 com.crab.spring.ioc.demo06.RepositoryB@309e345f com.crab.spring.ioc.demo06.RepositoryA@7a4ccb53
  从结果看,顺序是CBA,顺序符合预期。@Autowired注入Map
  只要map  的键类型是String  ,即使是类型化的 Map 实例也可以自动装配。
  定义一个类注入map并打印@Component public class Service3 {     @Autowired     private Map repositoryMap;      public void printMap() {         this.repositoryMap.entrySet().forEach(entry -> {             System.out.println(entry.getKey() + "--" + entry.getKey());         });     } }
  测试一下输出结果    @org.junit.Test     public void test_map() {         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo06/spring1.xml");         System.out.println("注入map的键值对如下:");         Service3 service3 = context.getBean(Service3.class);         service3.printMap();         context.close();     }  注入map的键值对如下: repositoryA--repositoryA repositoryB--repositoryB repositoryC--repositoryC
  从结果看,成功注入到map中了。@Autowired结合@Primary
  @Primary  指示当多个候选者有资格自动装配单值依赖项时,应优先考虑 该bean。
  先看一个不加@Primary  的案例。@Component @Order(0) // 指定注入集合时的顺序 public class RepositoryA implements RepositoryBase { }  @Component @Order(-1) public class RepositoryB  implements RepositoryBase { }  @Component @Order(-2) public class RepositoryC implements RepositoryBase{ } @Component public class Service4 {      @Autowired     private RepositoryBase repositoryBase;      @Override     public String toString() {         return "Service4{" +                 "repositoryBase=" + repositoryBase +                 "}";     } }
  由于容器中有3个RepositoryBase  ,Spring无法决定选择哪一个,因此会抛出UnsatisfiedDependencyException  如下。    @org.junit.Test     public void test_require() {         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo06/spring1.xml");         Service4 service4 = context.getBean(Service4.class);         System.out.println(service4);         context.close();     } org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name "service4": Unsatisfied dependency expressed through field "repositoryBase"; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type "com.crab.spring.ioc.demo06.RepositoryBase" available: expected single matching bean but found 3: repositoryA,repositoryB,repositoryC
  将RepositoryC  加上@Primary  @Component @Order(-2) @Primary public class RepositoryC implements RepositoryBase{ }
  再运行上面的测试,成功注入了RepositoryC  。Service4{repositoryBase=com.crab.spring.ioc.demo06.RepositoryC@4df50bcc} @Autowired配合Optional
  @Autowired  有个属性required  指示依赖是否是非必须即可选的,默认是false  。可以用java.util.Optional  包装下。/**  * @author zfd  * @version v1.0  * @date 2022/1/14 11:54  * @关于我 请关注公众号 螃蟹的Java笔记 获取更多技术系列  */ @Component public class Service5 {     private RepositoryA repositoryA;      public RepositoryA getRepositoryA() {         return repositoryA;     }     @Autowired     public void setRepositoryA(Optional repositoryOptional) {         RepositoryA repositoryA = repositoryOptional.orElseGet(() -> new RepositoryA());         this.repositoryA = this.repositoryA;     } }
  从 Spring Framework 5.0 开始,还可以使用 @Nullable   注解来表达可空的概念。@Component public class Service6 {     private RepositoryA repositoryA;      @Autowired     public void setRepositoryA(@Nullable RepositoryA repositoryA) {         this.repositoryA = this.repositoryA;     } } 配合@Qualifier
  上面提到,当容器中具有多个实例需要确定一个主要候选人时,@Primary 是一种使用类型自动装配的有效方法,具有多个实例。当需要对选择过程进行更多控制时,也可以使用 Spring 的 @Qualifier 注解。通过限定符值与特定参数相关联,缩小类型匹配的范围,以便为每个参数选择特定的 bean。来看案例。快速使用
  依赖类的配置@Component @Order(0) public class RepositoryA implements RepositoryBase { }  @Component("repositoryB") // 指定了名称 @Order(-1) public class RepositoryB  implements RepositoryBase { }  @Component @Order(-2) @Primary  // 标记为主要的候选者 public class RepositoryC implements RepositoryBase{ }
  @Qualifier  在字段和构造函数上指定bean的名称@Component public class Service7 {     // 指定注入repositoryB     @Autowired     @Qualifier("repositoryB")     private RepositoryBase repository;      private RepositoryBase repository2;      // 在构造函数中指定注入repositoryA     @Autowired     public Service7(@Qualifier("repositoryA") RepositoryBase repository2) {         this.repository2 = repository2;     }     // 省略 }
  测试一下,观察输出结果。    @org.junit.Test     public void test_qualifier() {         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo06/spring1.xml");         Service7 service7 = context.getBean(Service7.class);         System.out.println(service7);         context.close();     } Service1{repository=com.crab.spring.ioc.demo06.RepositoryB@222114ba, repository2=com.crab.spring.ioc.demo06.RepositoryA@16e7dcfd}
  结论:RepositoryC  标记了@Primary  注解,正常情况下会注入该类实例。通过@Qualifier  指定注入了RepositoryB  和RepositoryA  ,验证成功。总结
  本文介绍了基于注解的Spring容器配置,简化了xml配置文件的编写,提供了2个快速入门案例。重点分析了@Autowired  配合各种注解灵活注入依赖覆盖场景。下一篇介绍在基础上介绍更多的注解和类路径的扫描。
  本篇源码地址: https://github.com/kongxubihai/pdf-spring-series/tree/main/spring-series-ioc/src/main/java/com/crab/spring/ioc/demo06

恶意诱导消费,中国移动坑人本人是中国移动的忠实客户,此号码已使用近30年。去年初,有客服打电话说我是老客户,建议我办个套餐会更实惠。我信了,办了每月68元的套餐,费用上去了,手机的使用情况如故今年8月,又有赣锋锂业三安光电,长电科技,华天科技,通富微电,天齐锂业加油伊利股份牛奶,亿利节能光伏,至纯科技大基金二期入股,三安光电半导体,湖北宜化磷化工,牧原股份猪肉,芯能科技光伏概念,包钢股份,隆基股份光伏行业清洁能源的公司,也是国家重点支持的产业LinuxShell基本运算符想玩转linux就请一直看下去我是IT悟道,点击右上方关注,每天分享IT科技数码方面的干货。Shell基本运算符Shell和其他编程语言一样,支持多种运算符,包括算数运算符关系运算符布尔运算符字符串运算符文件测郭台铭彻底失算,曾被踢出果链的欧菲光,强势反击打脸苹果提到富士康应该无人不知吧,富士康自从掌握了苹果的大单之后,就成为了世界级的企业。郭台铭作为富士康的掌控者,此时的命运就跟苹果捆绑在了一起。当苹果开始实行去中国化需要迁出中国市场时,天猫新店完善店铺信息农村淘宝要不要加入?针对天猫入驻后台品牌信息这部分未标注的问题,其实不难判断出,除了基础的资质之外,这些信息是天猫对品牌评估时候的加分项目。当然你会说很多朋友申请的时候,也没有填写也能通过。这个不是必小米12Pro搭载真LTPO?雷军屏幕天花板今年一众LTPO机型,都LTPO了个寂寞,发布会上各种吹,实际到手还是白名单锁帧,手指离开屏幕降为60赫兹,直到iPhone13ProProMotion的出现才算真正利用好了LTP手机号码识别OCR技术算法记得在两年前就有一个快递行业的朋友向我咨询,有没有APP可以直接识别出快递单上的手机号码,然后进行拨打电话,这样他就不用每天用手机键盘去一个个的输入数字了。每天他的员工每个人都要打为什么苹果手机基本不涨价,国产手机却越卖越贵?自从2009年苹果首次进入中国以后,就以高达5000元的售价,在消费者心中坐实了高端手机品牌的形象。那个时候的国产手机还以山寨机为主,售价都很低廉,大部分都是在1千元左右。直到后面售价8988元起,华为首款纵向折叠屏手机P50Pocket发布阿里云回应漏洞风波Python3。6生命周期中止极客头条CSDN的读者朋友们早上好哇,极客头条来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧。整理梦依丹出品CSDN(IDCSDNnews)一分钟速览新闻点!阿里云回应开源社区Ap推荐几款性价比极高的二手手机,现在入手是真的香啊第一款华为mate30pro现在咸鱼上基本都在2000左右。在配置上麒麟990处理器,4500mAh电池40W线充27W无线充,后置4000万徕卡四摄,另外这款旗舰还采用了石墨烯薄转转集团即时手机行情华为P50Pocket发布首日二手市场加价预售12月24日消息,昨天,华为P50Pocket折叠屏手机正式发布,8256GB版售价为8988元,12512GB艺术定制版售价为10988元。值得注意的是,发布会一结束,转转平台的
扶助数字贫困户摆脱贫困,让一码通行真正普惠全民2020年是特殊的一年,在疫情防控常态化的这一年,数字技术在疫情防控中发挥了重要作用。自杭州市首创杭州健康码应用之后,健康码通过数据技术,实现了疫情精准防控,在全国各地得到迅速推广直播带货就是新农活,网红主播也可以是三八红旗手继担任全国青联委员后,网红主播薇娅在今天被授予了三八红旗手荣誉称号!2020年是特殊的一年,因为疫情的影响,农村道路封阻物流运输的困难人力成本攀升等种种原因导致我国很多产品滞销,而常程否认签字被打脸!人无信不立,雷军这次真的找对人了么这一次,雷军找的是原联想公司中国区手机业务负责人常程。今年中,雷军举行了一场一往无前的发布会,讲述了这10年小米的成功和创业的曲折,特别提到了他在创业初期的经历。雷军说,创业要找人从10,000美金交易盈利到100万美金,需要多长时间?很多人交易差价合约股票期货等其他工具,明知道这些交易的风险高,但是抵挡不住大家对财富的向往。就像权力的游戏中乔拉骑士率领先锋部队冲向夜王异鬼,前方充满未知恐惧和黑暗,最后结果往往令分析今年底前黄金将涨至每盎司2000美元德国商业银行(Commerzbank)表示,5月黄金价格上升近8,创下自2020年7月以来最显著的月度涨幅。数据显示,黄金ETF的旺盛购买量推动了这一趋势,估计相关ETF的购买量总高盛集团美元将重演数年来最疲软走势高盛集团(GoldmanSachs)预计,美元将会再次重演近年最疲软的走势,而摩根士丹利则认为美元指数会向上。高盛指出,逆差是其看跌美元的关键,该行分析师ZachPandl称当前与ATFX连续三季度保持增长,MT4交易量稳居全球排名前五ATFX动态近期,金融行业权威媒体FinanceMagnates发布了全球经纪商最为关注的2021年第一季度的行业报告(IntelligenceReport),该报告详细的介绍了全你无法想象,成功交易员原来是这样配比仓位的布雷特斯坦伯格(BrettSteenbarger)是美国知名交易心理导师,曾在华尔街多家顶级培训机构担任交易员心理导师。作为一名心理学教授和资深交易员,布雷特对交易心理的理解远胜他富爸爸穷爸爸作者比特币跌至27,000美元或再买入受中国方面的重拳打击,虚拟货币龙头比特币由4月高位6。48万美元水平急挫,如今价格已接近腰斩。据统计,5月比特币累计跌幅逾37,或成10年来最差月度表现。尽管比特币可能要创下201ATFX再添新品,50余种港股CFD震撼上线ATFX动态众所周知,港股在全球都具有强大的竞争力。随着全球金融市场的蓬勃发展,投资者对差价合约产品的多样性需求日益增加,越来越多的投资者希望经纪商能为其提供港股产品,让他们能通过AFAQ集团2021年JFEX旗舰活动将于6月29至30日全方位虚拟会议呈现中东和北非地区著名展览组织者AFAQ集团宣布他们的旗舰活动JordanForexExpoandAwards(JFEX),将于今年夏天于2021年6月29日至30日回归。第18轮知名