Java注解

一、定义:
注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据。

 

二、作用:
①编写文档 :通过代码里标识的元数据生成文档【生成文档 doc 文档 @param @return @see @exception @version @author @since】
②编译检查 :通过代码里标识的元数据让编译器能够实现基本的编译检查【@Override @Deprecated [ˈdeprəkeɪtɪd] @SuppressWarnings】
③运行时分析:通过代码里标识的元数据对代码进行分析【使用反射解析注解】

 

三、注解与注释区别:
注释:是对代码的描述、说明, 编译器在编译生成字节码文件时一般会自动忽略注释,在运行时无法获取。
注解:可以存在于源文件、class 文件、以及程序运行时,是代码的一部分。

 

四、Java 内置三种标准注解:
① @Deprecated
  注解为不建议使用,可以用在 方法和类上。
  基本上这种方法和类都是因为升级或性能上面的一些原因废弃不建议使用,但是为了兼容或其他原因,还必须保留。
  所以就打上这个注解。
  在 Java 本身的 API 中就有很多这样的例子, 方法打上了这个注解,进到 Source code 会看到替代的新的方法是哪个。
  在 eclipse 中编写 code 时,添加此注解的方法在声明和调用的地方都会加上删除线。
② @Override
  覆盖超类中的方法。
  如果不小心拼写错误,或者方法签名对不上被覆盖的方法,编译器就会发出错误提示信息。
③ @SuppressWarnings
  忽略警告。
  如果你的 code 在转型或其他的部分有一些警告的话,但是你又想忽略这些警告,就可以使用这个注解了。
    1) deprecation 使用了不赞成使用的类或方法时的警告
    2) unchecked 执行了未检查的转换时警告
    3) fallthrough 当使用 switch 操作时 case 后未加入 break 操作,而导致程序继续执行其他 case 语句时出现的警告
    4) path 当设置一个错误的类路径、源文件路径时出现的警告
    5) serial 当在可序列化的类上缺少 serialVersionUID 定义时的警告
    6) fianally 任何 finally 子句不能正常完成时警告
    7) all 关于以上所有情况的警告

 

五、Java 内置四种元注解:
元注解的作用就是负责注解其他注解,在自定义注解的时候经常使用。
Java5.0 定义了 4 个标准的 meta-annotation 类型,它们被用来提供对其它 annotation 类型作说明。Java5.0 定义的元注解:
  1.@Target : 描述注解修饰对象范围
  2.@Retention : 描述注解存在的生命周期
  3.@Documented : 在 JavaDoc 中,包含此注解信息
  4. @Inhretied : 允许子类继承父类中的注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

@Target:
  @Target 说明了 Annotation 所修饰的对象范围:Annotation 可被用于 packages、types(类、接口、枚举、Annotation 类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch 参数)。在 Annotation 类型的声明中使用了 target 可更加明晰其修饰的目标。
  作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
  取值 (ElementType) 有:
    1.CONSTRUCTOR: 用于描述构造器
    2.FIELD: 用于描述域
    3.LOCAL_VARIABLE: 用于描述局部变量
    4.METHOD: 用于描述方法
    5.PACKAGE: 用于描述包
    6.PARAMETER: 用于描述参数
    7.TYPE: 用于描述类、接口 (包括注解类型) 或 enum 声明
               8.ANNOTATION_TYPE : 用于描述注解

@Retention:
  @Retention 定义了该 Annotation 被保留的时间长短:某些 Annotation 仅出现在源代码中,而被编译器丢弃;而另一些却被编译在 class 文件中;编译在 class 文件中的 Annotation 可能会被虚拟机忽略,而另一些在 class 被装载时将被读取(请注意并不影响 class 的执行,因为 Annotation 与 class 在使用上是被分离的)。使用这个 meta-Annotation 可以对 Annotation 的“生命周期”限制。
  作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
  取值(RetentionPoicy)有:
    1.SOURCE: 在源文件中有效(即源文件保留)
    2.CLASS: 在 class 文件中有效(即 class 保留)
    3.RUNTIME: 在运行时有效(即运行时保留)

@Documented:
  @Documented 用于描述其它类型的 annotation 应该被作为被标注的程序成员的公共 API,因此可以被例如 javadoc 此类的工具文档化。Documented 是一个标记注解,没有成员。

@Inherited:
  @Inherited 元注解是一个标记注解,@Inherited 阐述了某个被标注的类型是被继承的。如果一个使用了 @Inherited 修饰的 annotation 类型被用于一个 class,则这个 annotation 将被用于该 class 的子类。
  注意:@Inherited annotation 类型是被标注过的 class 的子类所继承。类并不从它所实现的接口继承 annotation,方法并不从它所重载的方法继承 annotation。
  当 @Inherited annotation 类型标注的 annotation 的 Retention 是 RetentionPolicy.RUNTIME,则反射 API 增强了这种继承性。如果我们使用 java.lang.reflect 去查询一个 @Inherited annotation 类型的 annotation 时,反射代码检查将展开工作:检查 class 和其父类,直到发现指定的 annotation 类型被发现,或者到达类继承结构的顶层。

 

 六、自定义注解:

使用 @interface 自定义注解时,自动继承了 java.lang.annotation.Annotation 接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface 用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过 default 来声明参数的默认值。

  定义注解格式:
  public @interface 注解名 {定义体}

  注解参数的可支持数据类型:

    1. 所有基本数据类型(int,float,boolean,byte,double,char,long,short)
    2.String 类型
    3.Class 类型
    4.enum 类型
    5.Annotation 类型
    6. 以上所有类型的数组

  Annotation 类型里面的参数该怎么设定: 
  第一, 只能用 public 或默认 (default) 这两个访问权修饰. 例如,String value(); 这里把方法设为 defaul 默认类型;   
  第二, 参数成员只能用基本类型 byte,short,char,int,long,float,double,boolean 八种基本数据类型和 String,Enum,Class,annotations 等数据类型, 以及这一些类型的数组. 例如,String value(); 这里的参数成员就为 String;  
  第三, 如果只有一个参数成员, 最好把参数名称设为 "value", 后加小括号.

 

七、自定义注解小例子:

 1. 定义英雄注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Hero {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">战士、巫师、刺客</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> HeroType{WARRIOR, WIZARD, ASSASSIN};

HeroType heroType() </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> HeroType.WARRIOR;

}

 2. 定义技能注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Skill {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">普通技能、终极技能</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">enum</span><span style="color: rgba(0, 0, 0, 1)"> SkillType{NORNAL, FINAL};

String skillDesc() </span><span style="color: rgba(0, 0, 255, 1)">default</span> ""<span style="color: rgba(0, 0, 0, 1)">;

SkillType skillType() </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> SkillType.NORNAL;

}

3. 定义抽象英雄类

public abstract class AbstractHero {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">英雄名称</span>
<span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String heroName;

AbstractHero(String heroName){
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.heroName =<span style="color: rgba(0, 0, 0, 1)"> heroName;
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">一技能</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Q();

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">二技能</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> W();

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">三技能</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> E();

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">终极技能</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> R();

</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getHeroName() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> heroName;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setHeroName(String heroName) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.heroName =<span style="color: rgba(0, 0, 0, 1)"> heroName;
}

}

4. 定义两个英雄类

@Hero(heroType = HeroType.WARRIOR)
public class Tiny extends AbstractHero{
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Tiny() {
    </span><span style="color: rgba(0, 0, 255, 1)">super</span>("小小"<span style="color: rgba(0, 0, 0, 1)">);
}

@Skill(skillDesc </span>= "造成1.2秒眩晕"<span style="color: rgba(0, 0, 0, 1)">)
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Q() {
    System.out.println(</span>"山崩"<span style="color: rgba(0, 0, 0, 1)">);
}

@Skill(skillDesc </span>= "起飞"<span style="color: rgba(0, 0, 0, 1)">)
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> W() {
    System.out.println(</span><span style="color: rgba(0, 0, 255, 1)">this</span>.getHeroName() + "释放了:投掷"<span style="color: rgba(0, 0, 0, 1)">);
}

@Skill(skillDesc </span>= "抗揍神技"<span style="color: rgba(0, 0, 0, 1)">)
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> E() {
    System.out.println(</span><span style="color: rgba(0, 0, 255, 1)">this</span>.getHeroName() + "释放了:崎岖外表"<span style="color: rgba(0, 0, 0, 1)">);
}

@Skill(skillType </span>= SkillType.FINAL , skillDesc = "攻速减半"<span style="color: rgba(0, 0, 0, 1)">)
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> R() {
    System.out.println(</span><span style="color: rgba(0, 0, 255, 1)">this</span>.getHeroName() + "释放了:长大"<span style="color: rgba(0, 0, 0, 1)">);
}

}

 

@Hero(heroType = HeroType.WIZARD)
public class Ezalor extends AbstractHero{
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Ezalor() {
    </span><span style="color: rgba(0, 0, 255, 1)">super</span>("甘道夫"<span style="color: rgba(0, 0, 0, 1)">);
}

@Skill(skillDesc </span>= "冲击波冲击波"<span style="color: rgba(0, 0, 0, 1)">)
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Q() {
    System.out.println(</span><span style="color: rgba(0, 0, 255, 1)">this</span>.getHeroName() + "释放了:冲击波"<span style="color: rgba(0, 0, 0, 1)">);
}

@Skill(skillDesc </span>= "法力流失"<span style="color: rgba(0, 0, 0, 1)">)
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> W() {
    System.out.println(</span><span style="color: rgba(0, 0, 255, 1)">this</span>.getHeroName() + "释放了:法力流失"<span style="color: rgba(0, 0, 0, 1)">);
}

@Skill(skillDesc </span>= "查克拉魔法"<span style="color: rgba(0, 0, 0, 1)">)
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> E() {
    System.out.println(</span><span style="color: rgba(0, 0, 255, 1)">this</span>.getHeroName() + "释放了:查克拉魔法"<span style="color: rgba(0, 0, 0, 1)">);
}

@Skill(skillType </span>= SkillType.FINAL , skillDesc = "光之守卫"<span style="color: rgba(0, 0, 0, 1)">)
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> R() {
    System.out.println(</span><span style="color: rgba(0, 0, 255, 1)">this</span>.getHeroName() + "释放了:光之守卫"<span style="color: rgba(0, 0, 0, 1)">);
}

}

5. 定义测试类

public class HeroResover {
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args){
    createOnlyWarrior();
    
    createOnlyWarriorFinalSkill();
}

</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
 * 创建hero包中的所有战士,并释放Q技能
 </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> createOnlyWarrior(){
    
    String basePackage </span>= "com.hand.jeb.class1.heros"<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取hero包下所有类</span>
    List&lt;String&gt; clazzNameList =<span style="color: rgba(0, 0, 0, 1)"> PackageUtil.getClassName(basePackage);
    
    </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)">(String clazzName : clazzNameList){
        System.out.println(clazzName);
        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            Class</span>&lt;?&gt; heroClazz =<span style="color: rgba(0, 0, 0, 1)"> Class.forName(clazzName);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取Hero注解</span>
            Hero heroAnnotation = heroClazz.getAnnotation(Hero.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果类具有 @Hero注解,并且HeroType为WARRIOR</span>
            <span style="color: rgba(0, 0, 255, 1)">if</span>(heroAnnotation != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> HeroType.WARRIOR.equals(heroAnnotation.heroType())){
                AbstractHero warrior </span>=<span style="color: rgba(0, 0, 0, 1)"> (AbstractHero) heroClazz.newInstance();
                warrior.Q();
            }
            
        } </span><span style="color: rgba(0, 0, 255, 1)">catch</span> (ClassNotFoundException | InstantiationException |<span style="color: rgba(0, 0, 0, 1)"> IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    
}

</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
 * 创建hero包中的所有战士,并释放终极技能
 </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> createOnlyWarriorFinalSkill(){
    
    String basePackage </span>= "com.hand.jeb.class1.heros"<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取hero包下所有类</span>
    List&lt;String&gt; clazzNameList =<span style="color: rgba(0, 0, 0, 1)"> PackageUtil.getClassName(basePackage);
    
    </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)">(String clazzName : clazzNameList){
        System.out.println(clazzName);
        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            Class</span>&lt;?&gt; heroClazz =<span style="color: rgba(0, 0, 0, 1)"> Class.forName(clazzName);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取Hero注解</span>
            Hero heroAnnotation = heroClazz.getAnnotation(Hero.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(heroAnnotation != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> HeroType.WARRIOR.equals(heroAnnotation.heroType())){
                AbstractHero warrior </span>=<span style="color: rgba(0, 0, 0, 1)"> (AbstractHero) heroClazz.newInstance();
                Method[] methods </span>=<span style="color: rgba(0, 0, 0, 1)"> heroClazz.getMethods();
                </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)">(Method method : methods){
                    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">System.out.println(method.getName());</span>
                    Skill skillAnnotation = method.getAnnotation(Skill.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
                    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果方法上有终极技能注解则释放</span>
                    <span style="color: rgba(0, 0, 255, 1)">if</span>(skillAnnotation != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> SkillType.FINAL.equals(skillAnnotation.skillType())){
                        method.invoke(warrior);
                    }
                }
            }
            
        } </span><span style="color: rgba(0, 0, 255, 1)">catch</span> (ClassNotFoundException | InstantiationException |<span style="color: rgba(0, 0, 0, 1)"> IllegalAccessException 
                </span>| IllegalArgumentException |<span style="color: rgba(0, 0, 0, 1)"> InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    
}

}

 

八、Spring、SpringMVC 常用注解:

 1、@Component 是所有受Spring 管理组件的通用形式,相当于一个 JavaBean

 将上面的小例子作出修改,在英雄类上增加 @Compent 注解,并在 Spring 配置文件中增加包扫描

<context:component-scan base-package="com.hand.jeb.class1.heros"/>

 

 创建 Spring 测试类

public class HeroSpringResover {
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> ApplicationContext ctx = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> ApplicationContext getContextInstance(){
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(ctx != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
        </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ctx;
    </span><span style="color: rgba(0, 0, 255, 1)">else</span>
        <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> GenericXmlApplicationContext("classpath:/spring/applicationContext.xml"<span style="color: rgba(0, 0, 0, 1)">);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> main(String[] args) {
    createOnlyWarrior();
}

</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
 * 创建hero包中的所有战士,并释放Q技能
 </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> createOnlyWarrior(){
    
    String basePackage </span>= "com.hand.jeb.class1.heros"<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取hero包下所有类</span>
    List&lt;String&gt; clazzNameList =<span style="color: rgba(0, 0, 0, 1)"> PackageUtil.getClassName(basePackage);
    
    </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)">(String clazzName : clazzNameList){
        System.out.println(clazzName);
        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            Class</span>&lt;?&gt; heroClazz =<span style="color: rgba(0, 0, 0, 1)"> Class.forName(clazzName);
            
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取Hero注解</span>
            Hero heroAnnotation = heroClazz.getAnnotation(Hero.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果类具有 @Hero注解,并且HeroType为WARRIOR</span>
            <span style="color: rgba(0, 0, 255, 1)">if</span>(heroAnnotation != <span style="color: rgba(0, 0, 255, 1)">null</span> &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> HeroType.WARRIOR.equals(heroAnnotation.heroType())){
                
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">AbstractHero warrior = (AbstractHero) heroClazz.newInstance();
                
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用Spring获取bean</span>
                <span style="color: rgba(255, 0, 0, 1)">AbstractHero warrior =</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"> (AbstractHero) getContextInstance().getBean(heroClazz);</span>
                
                warrior.Q();
            }
            
        } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
}

}

 

2、@Controller、@Service、@Repository,均继承自 @Component,区分控制层、业务层、数据访问层

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {String value() default "";
}

 

3、Spring 自动装配注解 @Resource、@Autowired、@Qualifier

  @Resource 默认是按照名称来装配注入的,只有当找不到与名称匹配的 bean 才会按照类型来装配注入

  @Autowired 默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合 @Qualifier 一起使用

  @Resource 注解是由 J2EE 提供,而 @Autowired 是由 Spring 提供,故减少系统对 spring 的依赖建议使用 @Resource 的方式

  @Resource 和 @Autowired 都可以书写标注在字段或者该字段的 setter 方法之上

<bean id="heroDao" class="com.hand.jeb.HeroImpl"></bean>
@Resource(name="heroDao")
private IHero hero;

@Autowired
//如果有多个类实现了同一个接口,需要使用 Qualifier 区分
@Qualifier("heroDao")
private IHero hero;

 

 

4、@Transactional,事务注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> @AliasFor注解可用于声明一双别名属性,来给注解的属性起别名</span>
@AliasFor("transactionManager"<span style="color: rgba(0, 0, 0, 1)">)
String value() </span><span style="color: rgba(0, 0, 255, 1)">default</span> ""<span style="color: rgba(0, 0, 0, 1)">;

@AliasFor(</span>"value"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 可选的限定描述符,指定使用的事务管理器,同value</span>
String transactionManager() <span style="color: rgba(0, 0, 255, 1)">default</span> ""<span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">可选的事务传播行为设置</span>
Propagation propagation() <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> Propagation.REQUIRED;

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">可选的事务隔离级别设置</span>
Isolation isolation() <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> Isolation.DEFAULT;

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">事务超时时间</span>
<span style="color: rgba(0, 0, 255, 1)">int</span> timeout() <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> TransactionDefinition.TIMEOUT_DEFAULT;

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">读写或只读事务,默认读写</span>
<span style="color: rgba(0, 0, 255, 1)">boolean</span> readOnly() <span style="color: rgba(0, 0, 255, 1)">default</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">导致事务回滚的异常类数组</span>
Class&lt;? <span style="color: rgba(0, 0, 255, 1)">extends</span> Throwable&gt;[] rollbackFor() <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> {};

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">导致事务回滚的异常类名称数组</span>
String[] rollbackForClassName() <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> {};

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">不会导致事务回滚的异常类数组</span>
Class&lt;? <span style="color: rgba(0, 0, 255, 1)">extends</span> Throwable&gt;[] noRollbackFor() <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> {};

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">不会导致事务回滚的异常类名称数组</span>
String[] noRollbackForClassName() <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> {};

}


Propagation : 事务传播行为

事务传播行为类型

说明

PROPAGATION_REQUIRED

如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。

PROPAGATION_SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW

新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER

以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类 似的操作。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    Isolation: 事务隔离级别

事务隔离级别

说明

READ_UNCOMMITTED

读取未提交数据 (会出现脏读, 不可重复读) 基本不使用。

READ_COMMITTED

读取已提交数据 (会出现不可重复读和幻读)

REPEATABLE_READ

可重复读 (会出现幻读)

SERIALIZABLE

串行化

 

 

 

 

 

 

 

 

 

5、SpringMVC @RequestMapping,@RequestBody,@ResponseBody,@RequestParam,@PathVariable

@RequestMapping :SpringMVC 分发请求映射,属性 method = RequestMethod.POST/ RequestMethod.GET 可以限制请求类型

@RequestBody : 

该注解用于读取 Request 请求的 body 部分数据,使用系统默认配置的 HttpMessageConverter 进行解析,然后把相应的数据绑定到要返回的对象上;再把 HttpMessageConverter 返回的对象数据绑定到 controller 中方法的参数上。

使用时机:

A) GET、POST 方式提时, 根据 request header Content-Type 的值来判断:

  •     application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据 @RequestParam, @ModelAttribute 也可以处理,当然 @RequestBody 也能处理);
  •     multipart/form-data, 不能处理(即使用 @RequestBody 不能处理这种格式的数据);
  •     其他格式, 必须(其他格式包括 application/json, application/xml 等。这些格式的数据,必须使用 @RequestBody 来处理);

B) PUT 方式提交时, 根据 request header Content-Type 的值来判断:

  •     application/x-www-form-urlencoded, 必须;
  •     multipart/form-data, 不能处理;
  •     其他格式, 必须;

说明:request 的 body 部分的数据编码格式由 header 部分的 Content-Type 指定;

@ResponseBody

作用: 

      该注解用于将 Controller 的方法返回的对象,通过适当的 HttpMessageConverter 转换为指定格式后,写入到 Response 对象的 body 数据区。

使用时机:

      返回的数据不是 html 标签的页面,而是其他某种格式的数据时(如 json、xml 等)使用

@RequestParam

作用: 

A) 常用来处理简单类型的绑定,通过 Request.getParameter()获取的 String 可直接转换为简单类型的情况( String--> 简单类型的转换操作由 ConversionService 配置的转换器来完成);因为使用 request.getParameter() 方式获取参数,所以可以处理 get 方式中 queryString 的值,也可以处理 post 方式中 body data 的值;

B)用来处理 Content-Type: 为 application/x-www-form-urlencoded编码的内容,提交方式 GET、POST;

C) 该注解有两个属性: value、required; value 用来指定要传入值的 id 名称,required 用来指示参数是否必须绑定

@PathVariable

作用: 

当使用 @RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的 paramId 可通过 @Pathvariable 注解绑定它传过来的值到方法的参数上。