首页 文章 精选 留言 我的

精选列表

搜索[按需加载],共10000篇文章
优秀的个人博客,低调大师

【Spring注解驱动开发】使用@PropertySource加载配置文件,我只看这一篇!!

点击上方蓝色“冰河技术”,关注并选择“设为星标” 持之以恒,贵在坚持,每天进步一点点! 作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了精准定时调度方案,经受住了生产环境的考验。为使更多童鞋受益,现给出开源框架地址: https://github.com/sunshinelyz/mykit-delay PS: 欢迎各位Star源码,也可以pr你牛逼哄哄的代码。 写在前面 很多小伙伴都在问:冰河,你的Spring专题更新完了吗?怎么感觉像是写了一半啊?我:没有更新完呀,整个专题预计会有70多篇。那怎么更新了一半就去写别的了呢?那是因为有很多其他的小伙伴在后台留言说:急需学习一些其他的技术,所以,临时调整的。放心,Spring专题会持续更新的!这不,今天,我们就继续更新Spring专题。不出意外的话,会一直持续更新完!! 小伙伴们如果有啥疑问,可在文末点击“写留言”进行留言,我看到后会一一回复大家!! 项目工程源码已经提交到GitHub:https://github.com/sunshinelyz/spring-annotation @PropertySource注解概述 @PropertySource注解是Spring 3.1开始引入的配置类注解。通过@PropertySource注解将properties配置文件中的值存储到Spring的 Environment中,Environment接口提供方法去读取配置文件中的值,参数是properties文件中定义的key值。也可以使用@Value 注解用${}占位符注入属性。 @PropertySource注解的源代码如下所示。 packageorg.springframework.context.annotation;importjava.lang.annotation.Documented;importjava.lang.annotation.ElementType;importjava.lang.annotation.Repeatable;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;importorg.springframework.core.io.support.PropertySourceFactory;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Repeatable(PropertySources.class)public@interfacePropertySource{Stringname()default"";String[]value();booleanignoreResourceNotFound()defaultfalse;Stringencoding()default"";Class<?extendsPropertySourceFactory>factory()defaultPropertySourceFactory.class;} 从@PropertySource的源码可以看出,我们可以通过@PropertySource注解指定多个properties文件,可以使用如下形式进行指定。 @PropertySource(value={"classpath:xxx.properties","classpath:yyy.properties"}) 细心的读者可以看到,在@PropertySource注解类的上面标注了如下的注解信息。 @Repeatable(PropertySources.class) 看到这里,小伙伴们是不是有种恍然大悟的感觉呢?没错,我们也可以使用@PropertySources注解来指定properties配置文件。 @PropertySources注解 首先,我们也是看下@PropertySources注解的源码,如下所示。 packageorg.springframework.context.annotation;importjava.lang.annotation.Documented;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic@interfacePropertySources{PropertySource[]value();} @PropertySources注解的源码比较简单,只有一个PropertySource[]数组类型的属性value,那我们如何使用@PropertySources注解指定配置文件呢?其实也很简单,就是使用如下所示的方式就可以了。 @PropertySources(value={@PropertySource(value={"classpath:xxx.properties"}),@PropertySource(value={"classpath:yyy.properties"}),}) 是不是很简单呢?接下来,我们就以一个小案例来说明@PropertySource注解的用法。 案例准备 首先,我们在工程的src/main/resources目录下创建一个配置文件person.properties文件,文件的内容如下所示。 person.nickName=zhangsan 接下来,我们在Person类中新增一个字段nickName,如下所示。 packageio.mykit.spring.plugins.register.bean;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importlombok.ToString;importorg.springframework.beans.factory.annotation.Value;importjava.io.Serializable;/***@authorbinghe*@version1.0.0*@description测试实体类*/@Data@ToString@NoArgsConstructor@AllArgsConstructorpublicclassPersonimplementsSerializable{privatestaticfinallongserialVersionUID=7387479910468805194L;@Value("binghe")privateStringname;@Value("#{20-2}")privateIntegerage;privateStringnickName;} 目前,我们并没有为Person类的nickName字段赋值,所以,此时Person类的nickName字段的值为空。我们运行下PropertyValueTest类的testPropertyValue01()方法来看下输出结果,如下所示。 org.springframework.context.annotation.internalConfigurationAnnotationProcessororg.springframework.context.annotation.internalAutowiredAnnotationProcessororg.springframework.context.annotation.internalCommonAnnotationProcessororg.springframework.context.event.internalEventListenerProcessororg.springframework.context.event.internalEventListenerFactorypropertyValueConfigperson================================Person(name=binghe,age=18,nickName=null)Processfinishedwithexitcode0 可以看出,Person类的nickName字段的值确实输出了null。 使用xml文件方式获取值 如果我们需要在xml文件中获取person.properties文件中的值,则我们首先需要在Spring的xml文件中引入context名称空间,并且使用context命名空间导入person.properties文件,之后在bean的属性字段中使用如下方式将person.properties文件中的值注入到Person类的nickName字段上。 <context:property-placeholderlocation="classpath:person.properties"/><beanid="person"class="io.mykit.spring.plugins.register.bean.Person"><propertyname="name"value="binghe"></property><propertyname="age"value="18"></property><propertyname="nickName"value="${person.nickName}"></property></bean> 整个bean.xml文件的内容如下所示。 <?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/context/spring-context.xsd"><context:property-placeholderlocation="classpath:person.properties"/><beanid="person"class="io.mykit.spring.plugins.register.bean.Person"><propertyname="name"value="binghe"></property><propertyname="age"value="18"></property><propertyname="nickName"value="${person.nickName}"></property></bean></beans> 这样就可以将person.properties文件中的值注入到Person的nickName字段上。接下来,我们在PropertyValueTest类中创建testPropertyValue02()测试方法,如下所示。 @TestpublicvoidtestPropertyValue02(){ClassPathXmlApplicationContextcontext=newClassPathXmlApplicationContext("classpath:beans.xml");Personperson=(Person)context.getBean("person");System.out.println(person);} 我们运行PropertyValueTest类中创建的testPropertyValue02()方法,输出的结果信息如下所示。 Person(name=binghe,age=18,nickName=zhangsan) 使用注解方式获取值 如果我们使用注解的方式该如何做呢?首先,我们需要在PropertyValueConfig配置类上添加@PropertySource注解,如下所示。 packageio.mykit.spring.plugins.register.config;importio.mykit.spring.plugins.register.bean.Person;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.PropertySource;/***@authorbinghe*@version1.0.0*@description测试属性赋值*/@PropertySource(value={"classpath:person.properties"})@ConfigurationpublicclassPropertyValueConfig{@BeanpublicPersonperson(){returnnewPerson();}} 这里使用的@PropertySource(value = {"classpath:person.properties"})就相当于xml文件中使用的<context:property-placeholder location="classpath:person.properties"/>。 接下来,我们就可以在Person类的nickName字段上使用@Value注解来获取person.properties文件中的值了,如下所示。 @Value("${person.nickName}")privateStringnickName; 配置完成后,我们再次运行PropertyValueTest类的testPropertyValue01()方法来看下输出结果,如下所示。 org.springframework.context.annotation.internalConfigurationAnnotationProcessororg.springframework.context.annotation.internalAutowiredAnnotationProcessororg.springframework.context.annotation.internalCommonAnnotationProcessororg.springframework.context.event.internalEventListenerProcessororg.springframework.context.event.internalEventListenerFactorypropertyValueConfigperson================================Person(name=binghe,age=18,nickName=zhangsan) 可以看到,此时Person类的nickName字段已经注入了“zhangsan”这个值。 使用Environment获取值 这里,我们在PropertyValueTest类中创建testPropertyValue03()方法,来使用Environment获取person.properties中的值,如下所示。 @TestpublicvoidtestPropertyValue03(){AnnotationConfigApplicationContextcontext=newAnnotationConfigApplicationContext(PropertyValueConfig.class);Environmentenvironment=context.getEnvironment();StringnickName=environment.getProperty("person.nickName");System.out.println(nickName);} 运行PropertyValueTest类中的testPropertyValue03()方法,输出的结果信息如下所示。 zhangsan 可以看到,使用Environment确实能够获取到person.properties中的值。 重磅福利 关注「 冰河技术 」微信公众号,后台回复 “设计模式” 关键字领取《深入浅出Java 23种设计模式》PDF文档。回复“Java8”关键字领取《Java8新特性教程》PDF文档。回复“限流”关键字获取《亿级流量下的分布式限流解决方案》PDF文档,三本PDF均是由冰河原创并整理的超硬核教程,面试必备!! 好了,今天就聊到这儿吧!别忘了点个赞,给个在看和转发,让更多的人看到,一起学习,一起进步!! 写在最后 如果你觉得冰河写的还不错,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习高并发、分布式、微服务、大数据、互联网和云原生技术,「 冰河技术 」微信公众号更新了大量技术专题,每一篇技术文章干货满满!不少读者已经通过阅读「 冰河技术 」微信公众号文章,吊打面试官,成功跳槽到大厂;也有不少读者实现了技术上的飞跃,成为公司的技术骨干!如果你也想像他们一样提升自己的能力,实现技术能力的飞跃,进大厂,升职加薪,那就关注「 冰河技术 」微信公众号吧,每天更新超硬核技术干货,让你对如何提升技术能力不再迷茫! 后记: 记住:你比别人强的地方,不是你做过多少年的CRUD工作,而是你比别人掌握了更多深入的技能。不要总停留在CRUD的表面工作,理解并掌握底层原理并熟悉源码实现,并形成自己的抽象思维能力,做到灵活运用,才是你突破瓶颈,脱颖而出的重要方向! 你在刷抖音,玩游戏的时候,别人都在这里学习,成长,提升,人与人最大的差距其实就是思维。你可能不信,优秀的人,总是在一起。。 扫一扫或长按二维码 关注冰河技术微信公众号 如果你喜欢这篇文章,欢迎点赞和转发。 生活很美好,明天见(。・ω・。)ノ♡ 写留言 本文分享自微信公众号 - 冰河技术(hacker-binghe)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

优秀的个人博客,低调大师

基于超出内存可加载范围的数据集的逻辑回归分类器LR分类器

假如你想创建一个机器学习模型,但却发现你的输入数据集与你的计算机内存不相符?对于多机器的计算集群环境中通常可以使用如Hadoop和Apache Spark分布式计算工具。然而,Apache Spark能够在本地机器独立模式上,甚至在当输入数据集大于你的计算机内存时通过创建模型处理你的数据。 1.输入数据和预期结果 在上一篇文章我们讨论了“How To Find Simple And Interesting Multi-Gigabytes Data Set”,本文将使用上文中提及数据集的Posts.xml文件。文件大小是34.6千兆字节,这个xml文件包含stackoverflow.com文章数据作为xml属性: 标题 – 文章标题 主体 – 文章文本 标签 – 文章的标签列表 10+ 更多的xml -我们不需要使用的属性 关于stackoverflow.com的Posts.xml完整数据集信息请点击:https://archive.org/details/stackexchange. 另外我创建一个较小版本的这种文件,里面只有10个条目或文章。此文件包含一个小尺寸的原始数据集,这个数据是被知识共享许可批准的。 如你所料,这个小文件并不是模型训练的最好的选择(这个小模型训练文件并不是最好的选择),这个文件仅适用于实验数据准备代码。然而,本文中的端对端Spark脚本也适用于这个小文件,文件下载请点击这里。 我们的目标是创建一个可基于主体和标题预测文章标签的预测模型。为了精简任务和减少代码数量,我们将联接标题和主体并作为一个单独的文本列。 可想而知,这个模型在stackoverflow.com网站上是怎样工作的——用户键入一个问题,网站自动给予标签建议。 假设我们需要尽可能多的正确的标签,并且用户将消除不必要的标签。由于这个假设我们将选择撤销作为我们的模型高优先级目标。 2.二进制和多标签分类 栈溢出标记预测问题属于多标签分类的一种但并不唯一,因为模型应当预测许多分类。相同的文本将被归类为“Java”和“多线程”。注意多标签分类是不同的问题的一个泛化 ——多分类问题,从一组类预测为仅仅一个类。为了简化我们的第一个Apache Spark问题以及减少代码数量,让我们开始简化问题吧。取代练习一个多标记分类器,我们来对一个给定的标签练习一个简单的二进制分类器。例如,对标签“Java”,创建一个能够预测关于Java语言文章的分类器。 通过使用这个简单方法,可以创建几乎所有常见标签的分类器(Java, C++, Python, multi-threading等)。这是一个简单而易学的方法。然而,在实践中却并不完美,因为拆分预测模型基于各自的分类器,你忽略了类之间的相关性。另一个原因——训练许多分类器可能需要大量的计算。 3.在独立模式下设置和运行Apache Spark 如果你的机器上没有Apache Spark,从Spark官网上可以很容易下载到: http://spark.apache.org/,请下载使用1.5.1版本。spark-1.5.1版本的下载链接—— http://d3kbcqa49mib13.cloudfront.net/spark-1.5.1-bin-hadoop2.6.tgz。 如果Java在你的计算机上已经安装了,那么你可以准备启动Spark了,如果没有的话——请先安装Java。 在Unix系统和Macs系统上,解压缩该文件并复制到任意目录中。现在这个目录就是Spark的目录了。 运行Spark master: sbin/start-master.sh 运行spark slave: sbin/start-slaves.sh 运行Spark shell: bin/spark-shell Spark shell可以交互模式运行Scala命令。 Windows用户可以在这里找到命令:http://nishutayaltech.blogspot.in/2015/04/how-to-run-apache-spark-on-windows7-in.html 如果你工作在Hadoop环境的集群模式下,我假定你已经知道怎样运行Spark shell了。 4.导入库 对于这个端到端场景我们将使用Scala,也是Apache Spark的主要编程语言。 // General purpose library import scala.xml._ // Spark data manipulation libraries import org.apache.spark.sql.catalyst.plans._ import org.apache.spark.sql._ import org.apache.spark.sql.types._ import org.apache.spark.sql.functions._ // Spark machine learning libraries import org.apache.spark.ml.feature.{HashingTF, Tokenizer} import org.apache.spark.ml.classification .LogisticRegression import org.apache.spark.mllib.evaluation .BinaryClassificationMetrics import org.apache.spark.ml.Pipeline 5.解析XML 我们需要从输入的xml文件中提取主体、文本和标签,并用这些列创建一个单独的data-frame。首先,让我们移除xml的页眉和页脚。我假定输入文件和Spark shell命令位于同一目录下。 val fileName = "Posts.small.xml" val textFile = sc.textFile(fileName) val postsXml = textFile.map(_.trim). filter(!_.startsWith("<?xml version=")). filter(_ != "<posts>"). filter(_ != "</posts>") Spark具有良好的函数可用于解析json和csv格式。对于Xml,我们需要编写一些额外的代码行,通过规格化编码模式来创建一个数据框架。 注意,Scala语言自动转换所有xml代码,像“”转换到实际标签“”。我们也将连接标题和主体、移除所有的不必要的标签以及来自主体和所有空间副本的新行字符。 val postsRDD = postsXml.map { s => val xml = XML.loadString(s) val id = (xml \ "@Id").text val tags = (xml \ "@Tags").text val title = (xml \ "@Title").text val body = (xml \ "@Body").text val bodyPlain = ("<\\S+>".r).replaceAllIn(body, " ") val text = (title + " " + bodyPlain).replaceAll("\n", " ").replaceAll("( )+", " "); Row(id, tags, text) } 创建一个data-frame,schema应当应用于RDD(弹性分布式数据集,Resilient Distributed Datasets) val schemaString = "Id Tags Text" val schema = StructType( schemaString.split(" ").map(fieldName => StructField(fieldName, StringType, true))) val postsDf = sqlContext.createDataFrame(postsRDD, schema) 现在你可以查看一下你的数据框架了。 6.准备练习和测试数据集 下一步——为一个二进制分类器创建一个二进制标签。对这个代码示例,我们将用“java”作为一个标签,我们想要用一个二进制分类器来预测。所有存在“java”标签的行被标记为“1”,否则被标记为“0”。让我们来辨别我们的目标标记“java”和基于这个标记创建二进制标签。 val targetTag = "java" val myudf: (String => Double) = (str: String) => {if (str.contains(targetTag)) 1.0 else 0.0} val sqlfunc = udf(myudf) val postsLabeled = postsDf.withColumn("Label", sqlfunc(col("Tags")) ) 通过使用新标签,数据集可分为消极的子集和积极的子集。 val positive = postsLabeled.filter('Label > 0.0) val negative = postsLabeled.filter('Label < 1.0) 我们将使用数据的90%用于模型训练和另外10%作为数据集测试。让我们通过独立抽样积极和消极数据集来创建一个训练数据集吧。 val positiveTrain = positive.sample(false, 0.9) val negativeTrain = negative.sample(false, 0.9) val training = positiveTrain.unionAll(negativeTrain) 测试数据集应当包括训练数据集中不包括的所有的行。并且再次地——分别地处理积极样例和消极样例 val negativeTrainTmp = negativeTrain .withColumnRenamed("Label", "Flag").select('Id, 'Flag) val negativeTest = negative.join( negativeTrainTmp, negative("Id") === negativeTrainTmp("Id"), "LeftOuter").filter("Flag is null") .select(negative("Id"), 'Tags, 'Text, 'Label) val positiveTrainTmp = positiveTrain .withColumnRenamed("Label", "Flag") .select('Id, 'Flag) val positiveTest = positive.join( positiveTrainTmp, positive("Id") === positiveTrainTmp("Id"), "LeftOuter").filter("Flag is null") .select(positive("Id"), 'Tags, 'Text, 'Label) val testing = negativeTest.unionAll(positiveTest) 7.训练模型 定义训练参数: 1.特征数目 2.回归参数 3.梯度下降的样本点数目 Spark API 创建一个基于来自 data-frame和训练参数的列的模型 : val numFeatures = 64000 val numEpochs = 30 val regParam = 0.02 val tokenizer = new Tokenizer().setInputCol("Text") .setOutputCol("Words") val hashingTF = new org.apache.spark.ml.feature .HashingTF().setNumFeatures(numFeatures). setInputCol(tokenizer.getOutputCol) .setOutputCol("Features") val lr = new LogisticRegression().setMaxIter(numEpochs) .setRegParam(regParam)setFeaturesCol("Features") .setLabelCol("Label").setRawPredictionCol("Score") .setPredictionCol("Prediction") val pipeline = new Pipeline() .setStages(Array(tokenizer, hashingTF, lr)) val model = pipeline.fit(training) 8.测试模型 这是我们最后一段二进制“Java”分类器代码,将返回一个预测值(0.0或1.0): val testTitle = "Easiest way to merge a release into one JAR file" val testBoby = """Is there a tool or script which easily merges a bunch of href="http://en.wikipedia.org/wiki/JAR_%28file_format %29" JAR files into one JAR file? A bonus would be to easily set the main-file manifest and make it executable. I would like to run it with something like: As far as I can tell, it has no dependencies which indicates that it shouldn't be an easy single-file tool, but the downloaded ZIP file contains a lot of libraries.""" val testText = testTitle + testBody val testDF = sqlContext .createDataFrame(Seq( (99.0, testText))) .toDF("Label", "Text") val result = model.transform(testDF) val prediction = result.collect()(0)(6) .asInstanceOf[Double] print("Prediction: "+ prediction) 让我们评估基于训练数据集的模型的质量。 val testingResult = model.transform(testing) val testingResultScores = testingResult .select("Prediction", "Label").rdd .map(r => (r(0).asInstanceOf[Double], r(1) .asInstanceOf[Double])) val bc = new BinaryClassificationMetrics(testingResultScores) val roc = bc.areaUnderROC print("Area under the ROC:" + roc) 如果你使用的是小规模的数据集,那么你的模型质量可能不是最好的。ROC值下的面积将非常低(接近50%),意味着一个差的模型质量。如果使用的是整个的Post.xml数据集,质量就不会这么差,ROC下的面积是0.64。或许你可以通过考虑不同的转换,如TF-IDF和规范化来改善结果. 如果数据集超出计算内存承受范围的话,Apache Spark可能是数据处理和机器学习脚本的一个非常好的选择。在一个Hadoop Yarn集群模式环境中使用Spark或许不那么容易,但是,在本地或独立模式下,Spark跟其他分析工具一样简单。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册