Maven之——插件目标及绑定、命令行调用插件、目标前缀(插件前缀解析策略)、插件解析运行机制

来源:互联网 发布:论坛源码下载 编辑:程序博客网 时间:2024/06/08 04:13

1、    插件


        Maven三套生命周期定义各个阶段、不做任何实际工作、实际工作都是由插件来完成的、每个生命周期阶段都是由插件的目标来完成。

2、    插件目标(PluginGoal)


        Maven的核心仅仅定义了抽象的生命周期、具体的任务交由插件完成、插件以独立的形式存在、Maven会在需要的时候下载并使用插件。

        一个插件有可能有多个功能、每个功能就是一个目标。比如maven-dependency-plugin有十多个目标、每个目标对应了一个功能。插件的目标为dependency:analyze、dependency:tree和dependency:list。通用写法、冒号前面是插件前缀、冒号后面是插件的目标。比如compiler:compile。


3、    插件绑定


        Maven的生命周期与插件绑定、具体而言是生命周期的阶段与插件绑定、比如default生命周期的compile阶段可以由maven-compile-plugin插件的compile目标完成、将他们绑定就能实现编译的目的。


    3.1、    内置绑定


        Maven为实现快速构建、有一套内置的插件绑定。三套生命周期的插件绑定具体如下(其实是各个生命周期阶段与插件的目标的绑定)、其中default生命周期的构建方式会其打包类型有关、打包类型在POM中<packaging>packageType</packaging>指定、一般有jar、war两种类型、下面是 常用的jar的构建过程:

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1.                                                                         clean  
  2.   
  3. pre-clean          
  4. clean                                                                                                             maven-clean-plugin:clean  
  5. post-clean。  
  6.                                                                         site  
  7. pre-site  
  8. site:                                                                                                                maven-site-plugin:site  
  9. post-site  
  10. site-deploy:                                                                                      maven-site-plugin:deploy  
  11.   
  12.                                                                         default  
  13. process-resources                                maven-resources-plugin:resources  
  14. compile                                                                       maven-compiler-plugin:compile  
  15. process-test-resources            maven-resources-plugin:testResources  
  16. test-compile:                                      maven-compiler-plugin:testCompile  
  17. test:                                                                 maven-surefire-plugin:test  
  18. package                                                                       maven-jar-plugin:jar  
  19. install:                                                             maven-install-plugin:install  
  20. deploy:                                                            maven-deploy-plugin:deploy  


        上面三个生命周期中有很多原来的生命周期阶段没有默认绑定插件、也就意味着默认情况下他们没有任何意义。当然如果我们有自己特殊的处理、可以为他们绑定特殊的插件、比如下面会有提到的在打包的时候生成jar包的源码、可以在default生命周期的verify阶段绑定生成源码插件的生成源码的目标。


    3.2、    自定义绑定


        自定义绑定允许我们自己掌控插件目标与生命周期的结合、下面以生成项目主代码的源码jar为例。使用到的插件和他的目标为:maven-source-plugin:jar-no-fork、将其绑定到default生命周期阶段verify上(可以任意指定三套生命周期的任意阶段)、在项目的POM配置中(也可以在父POM中配置、后面聚合与继承会有提到)

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <build>  
  2.     <plugins>  
  3.         <plugin>  
  4.             <groupId>org.apache.maven.plugins</groupId>  
  5.             <artifactId>maven-source-plugin</artifactId>  
  6.             <version>2.1.1</version>  
  7.             <executions>  
  8.                 <execution>  
  9.                     <id>attach-sources</id>  
  10.                     <phase>verify</phase>  
  11.                     <goals>  
  12.                         <goal>jar-no-fork</goal>  
  13.                     </goals>  
  14.                 </execution>  
  15.             </executions>  
  16.         </plugin>  
  17.     </plugins>  
  18. </build>  

        上述配置有插件的坐标声明、还有excutions下面每个excution子元素配置的执行的一个个任务、通过phase指定与生命周期的那个阶段绑定、在通过goals指定执行绑定插件的哪些目标。

        当插件的目标绑定到不同的生命周期阶段的时候、插件目标的执行顺序是有生命周期阶段的顺序决定的、当多个插件目标绑定到同一生命周期阶段的时候、顺序是按照插件声明的顺序来决定目标的执行顺序。

==========================================

mvn -h显示mvn命令帮助:

复制代码
usage: mvn [options] [<goal(s)>] [<phase(s)>]Options: -am,--also-make                        If project list is specified, also                                        build projects required by the                                        list -amd,--also-make-dependents            If project list is specified, also                                        build projects that depend on                                        projects on the list -B,--batch-mode                        Run in non-interactive (batch)                                        mode -b,--builder <arg>                     The id of the build strategy to                                        use. -C,--strict-checksums                  Fail the build if checksums don't                                        match -c,--lax-checksums                     Warn if checksums don't match -cpu,--check-plugin-updates            Ineffective, only kept for                                        backward compatibility -D,--define <arg>                      Define a system property -e,--errors                            Produce execution error messages -emp,--encrypt-master-password <arg>   Encrypt master security password -ep,--encrypt-password <arg>           Encrypt server password -f,--file <arg>                        Force the use of an alternate POM                                        file (or directory with pom.xml). -fae,--fail-at-end                     Only fail the build afterwards;                                        allow all non-impacted builds to                                        continue -ff,--fail-fast                        Stop at first failure in                                        reactorized builds -fn,--fail-never                       NEVER fail the build, regardless                                        of project result -gs,--global-settings <arg>            Alternate path for the global                                        settings file -h,--help                              Display help information -l,--log-file <arg>                    Log file to where all build output                                        will go. -llr,--legacy-local-repository         Use Maven 2 Legacy Local                                        Repository behaviour, ie no use of                                        _remote.repositories. Can also be                                        activated by using                                        -Dmaven.legacyLocalRepo=true -N,--non-recursive                     Do not recurse into sub-projects -npr,--no-plugin-registry              Ineffective, only kept for                                        backward compatibility -npu,--no-plugin-updates               Ineffective, only kept for                                        backward compatibility -nsu,--no-snapshot-updates             Suppress SNAPSHOT updates -o,--offline                           Work offline -P,--activate-profiles <arg>           Comma-delimited list of profiles                                        to activate -pl,--projects <arg>                   Comma-delimited list of specified                                        reactor projects to build instead                                        of all projects. A project can be                                        specified by [groupId]:artifactId                                        or by its relative path. -q,--quiet                             Quiet output - only show errors -rf,--resume-from <arg>                Resume reactor from specified                                        project -s,--settings <arg>                    Alternate path for the user                                        settings file -T,--threads <arg>                     Thread count, for instance 2.0C                                        where C is core multiplied -t,--toolchains <arg>                  Alternate path for the user                                        toolchains file -U,--update-snapshots                  Forces a check for missing                                        releases and updated snapshots on                                        remote repositories -up,--update-plugins                   Ineffective, only kept for                                        backward compatibility -V,--show-version                      Display version information                                        WITHOUT stopping build -v,--version                           Display version information -X,--debug                             Produce execution debug output
复制代码

goal和phase分别指插件目标和生命周期阶段。

我们知道,可以通过mvn命令激活生命周期阶段,从而执行那些绑定在生命周期阶段上的插件目标。但Maven还支持直接从命令行调用插件目标。Maven支持这种方式是因为有些任务不适合绑定在生命周期上,例如maven-help-plugin:describe,我们不需要在构建项目的时候去描述插件信息。又如maven-dependency-plugin:tree,我们也不需要在构建项目的时候去显示依赖树。因此这些插件目标应该通过如下方式使用:

$ mvn help:describe -Dplugin=compiler

$ mvn dependency:tree

不过,这里还有一个疑问,describe是maven-help-plugin的目标没错,但冒号前面的help是什么呢?它既不是groupId,也不是artifactId,Maven是如何根据该信息找到对应版本插件的呢?同理,为什么不是maven-dependency-plugin:tree而是dependency:tree呢?

解答该疑问之前,可以先尝试一下如下的命令:

$ mvn org.apache.maven.plugins:maven-help-plugin:2.1:describe -Dplugin=compiler

$ mvn org.apache.maven.plugins:maven-dependency-plugin:2.1:tree

这两条命令就比较容易理解了。它们的效果与之前的两条命令基本是一样的,但显然前面的命令更简洁,更容易记忆和使用。为了达到该目的,Maven引入了目标前缀的概念。help是maven-help-plugin的目标前缀,dependency是maven-dependency-plugin的目标前缀,有了插件前缀,Maven就能找到对应的artifactId。不过仅有artifactId,而没有groupId和version,Maven是无法精确定位到某个插件的。那么,Maven是如何做到的呢?我们将在后面的文章详细剖析这个问题。

=============================================

插件前缀解析策略

当你执行maven的时候使用一个标准的生命周期,这些插件参与的生命周期就像是一个相当简单的进程。无论如何,当你从命令行中引用一个指令,例如clean,Maven必须有一些可靠的方式让clean插件前缀为maven-clean-plugin。这提供了简洁的命令行调用,当保存这些描述性的插件的真实工件id。

对于很多复杂性的问题,不是所有插件应该被强制使用同样的组id(在仓库中)。从这些组id在一个项目中假定被控制,和对于Maven多个项目可能使用的插件,它跟随着插件前缀匹配必须容纳多个插件组id。 对于地址关系,Maven提供了一块新的的仓库级别元数据(与任何单一的工件无关)对于插件组来说,在一个插件匹配管理者来组织多个插件组合提供功能性的搜索。

指定的插件前缀

为了给使用者方便的前缀去引用你的插件,一个前缀必须与你的插件相关在构建的时候。在默认的情况下,Maven将令一个猜想的前缀被使用,被移除任何被“maven”或者“plugin”的连字符在这些插件的工件id。方便的工件id格式被定为:

  • maven-${prefix}-plugin – 官方Apahe团队的插件(你不必使用这些命名的规则作为你的插件,看看更多的信息)
  • ${prefix}-maven-plugin – 其他来源的插件。

如果你的插件工件id符合这个规则,Maven将会根据元数据中正确的前缀自动匹配你插件的组id在仓库中的路径。无论如何,如果你想自定义前缀来引用的你插件,你可以指定前缀来引导通过配置参数在maven-plugin-plugin在你的pom中:

<project>  ...  <build>    ...    <plugins>      ...      <plugin>        <artifactId>maven-plugin-plugin</artifactId>        <version>2.3</version>        <configuration>          ...          <goalPrefix>somePrefix</goalPrefix>        </configuration>      </plugin>    </plugins>  </build></project>

以上的配置讲允许使用者引用你的插件通过前缀somePrefix,作为一个例子:

mvn somePrefix:goal

匹配前缀插件

对于每一个组id配置是为了搜索,Maven将:

  1. 从每一个远程仓库下载maven-metadata.xml到本地仓库,和命名为maven-metadata-${repoId}.xml 在内部使用 ${groupId}路径。
  2. 加载元数据文件,在maven-metadata-local.xml(如果存在)中,在内部使用 ${groupId}路径。合并它们。
  3. 发现插件前缀在合并元数据。如果它匹配,它应该引用一个具体的组和工件对。否则,继续在用户插件组中找下一个组id。 这些元数据文件组成的组(为了清晰当这些文件被大块在容器之外的目录),和一个组的插件节点。

在列表中每个插件包含一个前缀节点表示插件的命令行前缀,和一个工件节点, 提供的前缀映射对方提供了足够的信息来查找和使用插入部件。当一个插件被安装和发布,适当的元数据文件被放置和如果前缀匹配丢失了,修改前缀匹配。

配置Maven查找插件

默认情况下,maven将搜索组id org.apache.maven.plugins 为了前缀工件匹配插件,它需要在构建过程中执行。无论如何,前面提到的,使用者可能需要一个第三方的插件。从Maven项目被假定有控制的默认插件组,这意味着配置maven来搜索其他组的位置为了插件前缀匹配。

这很简单。在Maven配置文件(当前用户:${user.home}/.m2/settings.xml; 全局:${maven.home}/conf/settings.xml),你可以提供一个自定义的插件组项目,列出你想要搜索的插件(每个都在自己的plugingroup GroupID的子元素)。作为例子,如果我的项目使用了一个 模板文件,我可以设置:

<pluginGroups>  <pluginGroup>org.codehaus.modello</pluginGroup></pluginGroups>

这使我能够执行以下,这将从模式生成java类:

mvn -Dversion=4.0.0 -Dmodel=maven.mdo modello:java

Maven会搜索以下GroupID的搜索后,在用户设置中指定的任何插件组:

  • org.apache.maven.plugins
  • org.codehaus.mojo

注意:当指定被使用的插件组在搜索的前缀匹配中,秩序是关键!被指定的一个插件组 com.myco.plugins有一个前缀clean,我可以覆盖maven-clean-plugin的时候,当clean:clean被调用的时候。 笔记2:想了解更多信息可以查看 settings.xml

===========================================

Maven插件解析运行机制

这里给大家详细说一下Maven的运行机制,让大家不仅知其然,更知其所以然。

 

1.插件保存在哪里?

与我们所依赖的构件一样,插件也是基于坐标保存在我们的Maven仓库当中的。在用到插件的时候会先从本地仓库查找插件,如果本地仓库没有则从远程仓库查找插件并下载到本地仓库。

与普通的依赖构件不同的是,Maven会区别对待普通依赖的远程仓库与插件的远程仓库。前面提到的配置远程仓库只会对普通的依赖有效果。当Maven需要的插件在本地仓库不存在时是不会去我们以前配置的远程仓库查找插件的,而是需要有专门的插件远程仓库,我们来看看怎么配置插件远程仓库,在pom.xml加入如下内容:

复制代码
 1 <pluginRepositories> 2         <pluginRepository> 3             <id>nexus</id> 4             <name>nexus</name> 5             <url>http://192.168.0.70:8081/content/groups/public/</url> 6             <releases> 7                 <enabled>true</enabled> 8             </releases> 9             <snapshots>10                 <enabled>true</enabled>11             </snapshots>12         </pluginRepository>13 </pluginRepositories>
复制代码

大家可以发现,除了pluginRepositories和pluginRepository与以前配置远程仓库不同以外,其他的都是一样的,所代表的含义也是一样的。Maven的父POM中也是有内置一个插件仓库的,我现在用的电脑安装的是Maven 3.0.4版本,我们可以找到这个文件:${M2_HOME}/lib/maven-model-builder-3.0.4.jar,打开该文件,能找到超级父POM:\org\apache\maven\model\pom-4.0.0.xml,它是所有Maven POM的父POM,所有Maven项目都继承该配置。


我们来看看默认的远程插件仓库配置的是啥:

复制代码
 1 <pluginRepositories> 2     <pluginRepository> 3       <id>central</id> 4       <name>Central Repository</name> 5       <url>http://repo.maven.apache.org/maven2</url> 6       <layout>default</layout> 7       <snapshots> 8         <enabled>false</enabled> 9       </snapshots>10       <releases>11         <updatePolicy>never</updatePolicy>12       </releases>13     </pluginRepository>14 </pluginRepositories>
复制代码

默认插件仓库的地址就是中央仓库咯,它关闭了对snapshots的支持,防止引入snapshots版本的插件而导致不稳定的构件。一般来说,中央仓库所包含的插件完全能够满足我们的需要,只有在少数情况下才要配置,比如项目的插件无法在中央仓库找到,或者自己编写了插件才会配置自己的远程插件仓库。

 

2.插件命令运行解析

我们来看这样一个命令:

mvn compiler:compiler

这个命令会调用maven-compiler-plugin插件并执行compiler目标,大家有木有觉得很神奇?我们在pom.xml中配置插件往往是这样:

复制代码
1         <plugin>2             <groupId>org.apache.maven.plugins</groupId>3             <artifactId>maven-compiler-plugin</artifactId>4             <version>3.1</version>5             <configuration>6                 <source>1.7</source> <!-- 源代码使用的开发版本 -->7                 <target>1.7</target> <!-- 需要生成的目标class文件的编译版本 -->8             </configuration>9         </plugin>    
复制代码

maven-compiler-plugin插件默认执行的目标为compiler,那么命令的完整写法应该是:mvn org.apache.maven.plugins:maven-compiler-plugin:3.1:compiler才对啊,为什么mvn compiler:compiler也能完美的执行?

 

我们来看看Maven到底干了些神马来做到如此牛逼的功能:

 

①插件默认groupId

Maven默认以org.apache.maven.plugins作为groupId,到这里我们的命令应该是长这样的:

mvn org.apache.maven.plugins:compiler:compiler

我们也可以配置自己默认的groupId,在Maven的settings.xml中添加如下内容,前面提过最好将settings.xml放在用户目录的.m2下:

复制代码
1 <pluginGroups>2     <!-- pluginGroup3      | Specifies a further group identifier to use for plugin lookup.4     <pluginGroup>com.your.plugins</pluginGroup>5     -->6     <pluginGroup>com.your.plugins</pluginGroup>7 </pluginGroups>
复制代码

不过说实在的,没必要动他就别去动他了,我们用Maven只是解决一些刚需的问题,没必要的设置就尽量不去动他,别把Maven搞得太复杂,虽然Maven的却有点小复杂,跟大家扯这些只是希望大家能够对maven理解的更深入那么一点点,并不是建议大家一定要去使用某些东西,大家在平时的开发中要谨记这一点。

 

②我们来看看Maven插件远程仓库的元数据org/apache/maven/plugins/maven-metadata.xml,Maven默认的远程仓库是http://repo.maven.apache.org/maven2/,所有插件元数据路径则是:http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml,我们找到compiler插件的元数据,如图:

这里会根据prefix指定的前缀找到对应的artifactId,到这里我们的命令应该长成了这样:

mvn org.apache.maven.plugins:maven-compiler-plugin:compiler

 

③我们再根据groupId和artifactId找到maven-compiler-plugin插件单个的元数据,路径为http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-compiler-plugin/maven-metadata.xml,如图:

maven将所有的远程插件仓库及本地仓库元数据归并后,就能找到release的版本(maven3后为了保证项目构建的稳定性默认使用release版本),到这里命令就被扩展成为这样:

mvn org.apache.maven.plugins:maven-compiler-plugin:3.6.0:compiler

如果执行的是mvn compiler:compiler命令,由于maven-compiler-plugin的最新版本已经到了3.6.0,则默认会使用此版本。最后的compiler则是插件要执行的目标咯,看到这里大家应该明白mvn compiler:compiler命令为什么能够得到完美的运行了吧。

 

3.Maven超级POM

最后给大家把超级父POM贴出来,再次强调,如果我们没有在自己的pom.xml中配置相应的内容,则默认会使用超级父POM配置的内容。我现在用的电脑安装的是Maven 3.0.4版本,我们可以找到这个文件:${M2_HOME}/lib/maven-model-builder-3.0.4.jar,打开该文件,能找到超级父POM:\org\apache\maven\model\pom-4.0.0.xml,它是所有Maven POM的父POM,所有Maven项目都继承该配置。

复制代码
  1 <?xml version="1.0" encoding="UTF-8"?>  2   3 <!--  4 Licensed to the Apache Software Foundation (ASF) under one  5 or more contributor license agreements.  See the NOTICE file  6 distributed with this work for additional information  7 regarding copyright ownership.  The ASF licenses this file  8 to you under the Apache License, Version 2.0 (the  9 "License"); you may not use this file except in compliance 10 with the License.  You may obtain a copy of the License at 11  12     http://www.apache.org/licenses/LICENSE-2.0 13  14 Unless required by applicable law or agreed to in writing, 15 software distributed under the License is distributed on an 16 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 KIND, either express or implied.  See the License for the 18 specific language governing permissions and limitations 19 under the License. 20 --> 21  22 <!-- START SNIPPET: superpom --> 23 <project> 24   <modelVersion>4.0.0</modelVersion> 25  26   <repositories> 27     <repository> 28       <id>central</id> 29       <name>Central Repository</name> 30       <url>http://repo.maven.apache.org/maven2</url> 31       <layout>default</layout> 32       <snapshots> 33         <enabled>false</enabled> 34       </snapshots> 35     </repository> 36   </repositories> 37  38   <pluginRepositories> 39     <pluginRepository> 40       <id>central</id> 41       <name>Central Repository</name> 42       <url>http://repo.maven.apache.org/maven2</url> 43       <layout>default</layout> 44       <snapshots> 45         <enabled>false</enabled> 46       </snapshots> 47       <releases> 48         <updatePolicy>never</updatePolicy> 49       </releases> 50     </pluginRepository> 51   </pluginRepositories> 52  53   <build> 54     <directory>${project.basedir}/target</directory> 55     <outputDirectory>${project.build.directory}/classes</outputDirectory> 56     <finalName>${project.artifactId}-${project.version}</finalName> 57     <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory> 58     <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory> 59     <scriptSourceDirectory>src/main/scripts</scriptSourceDirectory> 60     <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory> 61     <resources> 62       <resource> 63         <directory>${project.basedir}/src/main/resources</directory> 64       </resource> 65     </resources> 66     <testResources> 67       <testResource> 68         <directory>${project.basedir}/src/test/resources</directory> 69       </testResource> 70     </testResources> 71     <pluginManagement> 72       <!-- NOTE: These plugins will be removed from future versions of the super POM --> 73       <!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) --> 74       <plugins> 75         <plugin> 76           <artifactId>maven-antrun-plugin</artifactId> 77           <version>1.3</version> 78         </plugin> 79         <plugin> 80           <artifactId>maven-assembly-plugin</artifactId> 81           <version>2.2-beta-5</version> 82         </plugin> 83         <plugin> 84           <artifactId>maven-dependency-plugin</artifactId> 85           <version>2.1</version> 86         </plugin> 87         <plugin> 88           <artifactId>maven-release-plugin</artifactId> 89           <version>2.0</version> 90         </plugin> 91       </plugins> 92     </pluginManagement> 93   </build> 94  95   <reporting> 96     <outputDirectory>${project.build.directory}/site</outputDirectory> 97   </reporting> 98  99   <profiles>100     <!-- NOTE: The release profile will be removed from future versions of the super POM -->101     <profile>102       <id>release-profile</id>103 104       <activation>105         <property>106           <name>performRelease</name>107           <value>true</value>108         </property>109       </activation>110 111       <build>112         <plugins>113           <plugin>114             <inherited>true</inherited>115             <artifactId>maven-source-plugin</artifactId>116             <executions>117               <execution>118                 <id>attach-sources</id>119                 <goals>120                   <goal>jar</goal>121                 </goals>122               </execution>123             </executions>124           </plugin>125           <plugin>126             <inherited>true</inherited>127             <artifactId>maven-javadoc-plugin</artifactId>128             <executions>129               <execution>130                 <id>attach-javadocs</id>131                 <goals>132                   <goal>jar</goal>133                 </goals>134               </execution>135             </executions>136           </plugin>137           <plugin>138             <inherited>true</inherited>139             <artifactId>maven-deploy-plugin</artifactId>140             <configuration>141               <updateReleaseInfo>true</updateReleaseInfo>142             </configuration>143           </plugin>144         </plugins>145       </build>146     </profile>147   </profiles>148 149 </project>150 <!-- END SNIPPET: superpom -->
复制代码

很多插件是超级父POM当中并没有配置的,如果用户使用某个插件时没有设定版本,那么则会根据我上述所说的规则去仓库中查找可用的版本,然后做出选择。在Maven2中,插件的版本会被解析至latest。也就是说,当用户使用某个非核心插件且没有声明版本的时候,Maven会将版本解析为所有可用仓库中的最新版本,latest表示的就是最新版本,而这个版本很有可能是快照版本。

当插件为快照版本时,就会出现潜在的问题。昨天还好好的,可能今天就出错了,其原因是这个快照版本发生了变化导致的。为了防止这类问题,Maven3调整了解析机制,当插件没有声明版本的时候,不再解析至latest,而是使用release。这样就避免了由于快照频繁更新而导致的不稳定问题。但是这样就好了吗?不写版本号其实是不推荐的做法,例如,我使用的插件发布了一个新版本,而这个release版本与之前的版本的行为发生了变化,这种变化依然可能导致我们项目的瘫痪。所以使用插件的时候,应该一直显式的设定版本,这也解释了Maven为什么要在超级父POM中为核心插件设定版本咯。

 

结束语:当你感到悲哀痛苦时,最好是去学些什么东西,学习会使你从悲哀痛苦中走出来,学习会使你永远立于不败之地。说实在的,不要太在意眼前所发生的一切,更重要的是培养自己的个人能力,如今待在公司亦或者跳槽,决定你能不能继续走下去的一定是你的个人能力,作为年轻人,在公司更看重的不应该是薪水的高低,而是公司能给你带来多大的成长环境。找个好的公司其实不比找个合适的女朋友简单,作为年轻人我们一定要不断的提升个人能力,就跟找女朋友似的,往往就是你越有本事就越能够不将就,你个人能力越强则越有选择公司的资本。




原创粉丝点击