Java---JUnita、注解与类加载器详解以及实例

JUnit软件测试技术(工具)

在项目中建立专门用户测试的包结构。

在Junit中,通过@Test注解,可以运行一个方法。

★ Junit注解说明

使用了@Test注解应该满足以下条件:

1) 必须是无参数的非静态方法。

2) 添加@Test注解的类,必须拥有一个无参数的公开构造

★ JUnit测试示例演示

1、运行完成后,可以在Junit的窗口上看到运行所用的时间和结果信息。

2、被测试程序的运行结果出现在控制台(Console)上。

“项目”代码:

package cn.hncu.user.dao.dao;
/**
 * @author 陈浩翔
 * @version 1.0  2016-5-4
 */
public interface UserDao {
    public abstract void fun1()throws Exception;
    public abstract void fun2();
    public abstract void fun3();
}
package cn.hncu.user.dao.impl;

import cn.hncu.user.dao.dao.UserDao;

/**
 * @author 陈浩翔
 * @version 1.0  2016-5-4
 */
public class UserDaoImpl implements UserDao{
    @Override
    public void fun1() throws Exception {
        System.out.println("fun1....");
    }
    @Override
    public void fun2() {
        System.out.println("fun2....");
    }
    @Override
    public void fun3() {
        System.out.println("fun3....");
    }
}
package cn.hncu.user.dao.factory;

import cn.hncu.user.dao.dao.UserDao;
import cn.hncu.user.dao.impl.UserDaoImpl;

/**
 * @author 陈浩翔
 * @version 1.0  2016-5-4
 */
public class UserDaoFactory {
    public static UserDao getUserDao(){
        return new UserDaoImpl();
    }
}

随便写了几个输出。。。

下面的是测试代码:

package cn.hncu.test;

import org.junit.Test;

import cn.hncu.user.dao.dao.UserDao;
import cn.hncu.user.dao.factory.UserDaoFactory;
import cn.hncu.user.dao.impl.UserDaoImpl;

/**
 * @author 陈浩翔
 * @version 1.0  2016-5-4
 */
//使用@Test的条件2:该类必须具有一个无参构造方法
public class TestUserDaoImpl {
    UserDao dao = UserDaoFactory.getUserDao();

    /**
     * 测试fun1()方法
     */
    //使用@Test的条件1:测试方法必须是非静态、无参
    @Test
    public void testFun1(){
        try {
            dao.fun1();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testFun2() {
        dao.fun2();
    }

    @Test
    public void testFun3() {
        dao.fun3();
    }

}

正确的演示结果:

错误的演示结果:(没有无参构造方法)

★ JUnit中的其它注解

@BeforeClass、@AfterClass、@Before、@After

package cn.hncu.test;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import cn.hncu.user.dao.dao.UserDao;
import cn.hncu.user.dao.factory.UserDaoFactory;
import cn.hncu.user.dao.impl.UserDaoImpl;

/**
 * @author 陈浩翔
 * @version 1.0  2016-5-4
 */

public class TestUserDaoImpl2 {
    UserDao dao = UserDaoFactory.getUserDao();

    //注意要加static
    @BeforeClass
    public static void initFirst(){
        System.out.println("finishEnd...");
    }

    //在每次运行@Test方法之前,都会先运行这个@Before的方法
    @Before
    public void init(){
        System.out.println("init...");
    }

    @Test
    public void testFun1(){
        try {
            dao.fun1();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
        /*运行结果
    finishEnd...
    init...
    fun1....
    finish...
    finishEnd...
    */

    @Test
    public void testFun2() {
        dao.fun2();
    }
    /*运行结果
    finishEnd...
    init...
    fun2....
    finish...
    finishEnd...
    */

    @Test
    public void testFun3() {
        dao.fun3();
    }
    /*运行结果
    finishEnd...
    init...
    fun3....
    finish...
    finishEnd...
    */

    //在每次运行@Test方法之后,都会最后运行这个@After的方法
    @After
    public void finish(){
        System.out.println("finish...");
    }

    //注意要加static
    @AfterClass
    public static void finishEnd(){
        System.out.println("finishEnd...");
    }

}

注解 ( Annotation )

★ 元数据

    所谓元数据就是数据的数据。也就是说,元数据是描述数据的。就象数据表中的字段一样,每个字段描述了这个字段下的数据的含义。
   元数据可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。许多元数据工具,如XDoclet,将这些功能添加到核心Java语言中,暂时成为Java编程功能的一部分。
    一般来说,元数据的好处分为三类:文档编制、编译器检查和代码分析。代码级文档最常被引用。元数据提供了一种有用的方法来指明方法是否取决于其他方法,它们是否完整,特定类是否必须引用其他类,等等。

★ 什么是注解

Java中的注解就是Java源代码的元数据,也就是说注解是用来描述Java源代码的。 基本语法就是:@后面跟注解的名称。

像前面演示的那几个都是注解。

★ Java中预定义注解

①Override:标识某一个方法是否正确覆盖了它的父类的方法。

(如果用了这个注解,但是父类中没有这个方法,就会报错)

②Deprecated:表示已经不建议使用这个类成员了。 它是一个标记注解。

(用了这个注解的,表示在下一个升级版本中,可能不会有这个方法了,但是会有类似功能的方法代替,会在注释中提出)

③SuppressWarnings:用来抑制警告信息。

(例如:压泛型的警告)

(这个是可以传参进去的,可以实现不同的功能)

自定义注解1

自定义注解的语法很简单,跟定义接口类似,只是在名称前面加上@符号。

★ 最简单的自定义注解

public @interface MyAnno {
}

★ 使用这个注解

和使用其他注解是一样的

@MyAnno
public class UserModel{
} 

★ 为注解添加成员

//定义
public @interface MyAnno {
  public String schoolName();
}
//使用
@MyAnno(schoolName="湖南城市学院")
public class UserModel{
}

★ 设置默认值

//定义
public @interface MyAnno {
  public String schoolName() default "湖南城市学院";
}
//使用1
@MyAnno
public class UserModel{
}
//使用2
@MyAnno(schoolName="城院Java高手训练营")
public class UserModel{
}

对注解的注解

package cn.hncu.anno;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface MyAnno {
}

☆指定目标 Target

在了解如何使用Target 之前,需要认识另一个类,该类被称为ElementType (通过API详细学习) ,它实际上是一个枚举。这个枚举定义了注释类型可应用的不同程序元素。

//如果都不写,就是随便在哪里都可以用

@Target({ ElementType.TYPE, ElementType.METHOD}) 

//这个注解可以在哪里用,TYPE-可以在类上面用,METHOD-可以在方法上用

☆设置保持性 Retention

RetentionPolicy (通过API详细学习)枚举类中定义了3种注解保持性,分别决定了Java 编译器以何种方式处理注解。

@Retention(RetentionPolicy.RUNTIME)

//运行时VM虚拟机也能识别这个注解,这个注解一直存在

@Retention(RetentionPolicy.SOURCE) 

//class文件中有这个注解,但是VM虚拟机运行时,忽略这个注解了。

(这是默认的)

☆添加公共文档 Documented

在默认的情况下在使用javadoc自动生成文档时,注解将被忽略掉。如果想在文档中也包含注解,必须使用Documented为文档注解。

☆设置继承 Inherited

在默认的情况下,父类的注解并不会被子类继承。如果要继承,就必须加上Inherited注解。

如何读取注解

要读取注解的内容,就需要使用反射的技术。

注意:要想使用反射得到注释信息,必须用@Retention(RetentionPolicy.RUNTIME)进行注解。

    /**
     * 分别读取类上的@MyAnno注解 和  方法上的@MyAnno注解
     */
    @Test
    public void readAnno(){
        //※※注意:MyAnno注解定义时,必须指定它的保持性为 RUNTIME,否则下面是读取不出注解的

        //以下方式是读取“声明在类上的”MyAnno注解
        Class c = UserModel.class;
        //boolean boo = c.isAnnotationPresent(cn.hncu.anno.MyAnno.class);
        //boolean boo = c.isAnnotationPresent(MyAnno.class);
        boolean boo = (c.getAnnotation(MyAnno.class)!=null);
        System.out.println(boo);

        //以下方式是读取“声明在方法上的”MyAnno注解
        Method ms[] = c.getDeclaredMethods();
        for(Method m:ms){
            if(m.isAnnotationPresent(MyAnno.class)){
                System.out.println(m.getName()+"方法上有@MyAnno注解");
            }
        }
    }

结果:

true
getAge方法上有@MyAnno注解
getId方法上有@MyAnno注解

类加载器

Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:

BootStrap, ExtClassLoader, AppClassLoader

    @Test
    public void systemLoaderDemo(){
        ClassLoader loader = Person.class.getClassLoader();
        System.out.println(loader);//AppClassLoader
        loader = loader.getParent();
        System.out.println(loader);//ExtClassLoader
        loader = loader.getParent();
        System.out.println(loader);//null
    }

因为BootStrap是最底层,用C写的,我们不能访问到,我们没有权限,所以输出就是null了。

类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap。

Java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级类装载器对象或者默认采用系统类装载器为其父级类加载。

☆类加载器的委托机制

通过API认识ClassLoader类

当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?

首先当前线程的类加载器去加载线程中的第一个类。如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。

还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。

每个类加载器加载类时,又先委托给其上级类加载器。当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?

对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的aa.jar包中后,运行结果为ExtClassLoader的原因。

演示不是classpath下的类,系统类加载器是无法加载的

Person类:

package cn.hncu;
/**
 *
 * @author 陈浩翔
 *
 * @version 1.0  2016-5-4
 */
public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}
    @Test
    public void loaderLocalClassDemo() throws ReflectiveOperationException{
        Class c = Class.forName("cn.hncu.Person");
        System.out.println(c);
        Object obj = c.newInstance();
        System.out.println(obj);
    }

运行结果:

class cn.hncu.Person
Person [name=null, age=0]

再看:

我把Person.class移到d:\cn\hncu

//不是classpath下的类,系统类加载器是无法加载的---如果要加载,得自己写类加载器
@Test
    public void loaderRemoteClassDemo() throws ReflectiveOperationException{
        Class c = Class.forName("d:\\cn\\hncu\\Person.class");
        System.out.println(c);
        Object obj = c.newInstance();
        System.out.println(obj);
    }

结果:

挂了,不能运行了。

因为没有配置classpath。

对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的aa.jar包中后,运行结果为ExtClassLoader

必须是压.class文件,不要压缩.java文件。!!!!

package cn.hncu;

/**
 *
 * @author 陈浩翔
 *
 * @version 1.0  2016-5-4
 */
public class LoaderDemo {
    public static void main(String[] args) {
        LoaderDemo a = new LoaderDemo();
        System.out.println(a);
    }

    @Override
    public String toString() {
        return "随便演示。。。chx";
    }
}

先按照这个命令打包这个.java

package cn.hncu;

/**
 *
 * @author 陈浩翔
 *
 * @version 1.0  2016-5-4
 */
public class LoaderDemo {
    public static void main(String[] args) {
        LoaderDemo a = new LoaderDemo();
        System.out.println(a);
    }

    @Override
    public String toString() {
        return "湖南城院。。。随便演示...chx";
    }
    //改了没用。已经不会运行这里的代码了。
}

大家看输出结果:

对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的aa.jar包中后,运行结果还是为ExtClassLoader。

也就是那三层从上到下,如果上面已经有那个类了,就不会运行下面的那个类:

BootStrap—>ExtClassLoader—>AppClassLoader(System classLoader)

大家再看看这个图,是不是感觉容易理解一些了:

时间: 2024-10-10 01:47:36

Java---JUnita、注解与类加载器详解以及实例的相关文章

Java学习-007-Log4J 日志记录配置文件详解及实例源代码

此文主要讲述在初学 Java 时,常用的 Log4J 日志记录配置文件详解及实例源代码整理.希望能对初学 Java 编程的亲们有所帮助.若有不足之处,敬请大神指正,不胜感激!源代码测试通过日期为:2015-1-30 13:54:02,请知悉. 所需的 jar 包下载链接为:http://yunpan.cn/cKE56sxqtQCfP  访问密码 63d8 有关 Log4J 日志文件中日志级别及文件配置的详细情况,在 Log4J 的配置文件(xml.properties)中有详细的介绍,敬请参阅!

GLSL-几何着色器详解跟实例(GS:Geometry Shader)[转]

[OpenGL4.0]GLSL-几何着色器详解和实例(GS:Geometry Shader) 一.什么是几何着色器(GS:Geometry Shader) Input Assembler(IA)从顶点缓冲区上的输入流中接收顶点数据,并且把数据项转换为规范的格式.vertex shader通常用来把顶点从模型空间变换到平面空间,vertex shader读取一个顶点,输出一个顶点.Pixel Shader读取单一pixel属性,输出包含颜色和Z信息的的片断.而geometry shader是Dir

Java高新技术第一篇:类加载器详解

首先来了解一下字节码和class文件的区别: 我们知道,新建一个Java对象的时候,JVM要将这个对象对应的字节码加载到内存中,这个字节码的原始信息存放在classpath(就是我们新建Java工程的bin目录下)指定的目录下的.class文件,类加载需要将.class文件导入到硬盘中,经过一些处理之后变成字节码在加载到内存中. 下面来看一下简单的例子: [java] view plain copy package com.loadclass.demo; import java.util.Dat

[转载] Java高新技术第一篇:类加载器详解

本文转载自: http://blog.csdn.net/jiangwei0910410003/article/details/17733153 首先来了解一下字节码和class文件的区别: 我们知道,新建一个Java对象的时候,JVM要将这个对象对应的字节码加载到内存中,这个字节码的原始信息存放在classpath(就是我们新建Java工程的bin目录下)指定的目录下的.class文件,类加载需要将.class文件导入到硬盘中,经过一些处理之后变成字节码在加载到内存中. 下面来看一下简单的例子:

类加载器详解

首先来了解一下字节码和class文件的区别: 我们知道,新建一个java对象的时候,JVM要将这个对象对应的字节码加载到内存中,这个字节码的原始信息存放在classpath(就是我们新建Java工程的bin目录下)指定的目录下的.class文件,类加载需要将.class文件导入到硬盘中,经过一些处理之后变成字节码在加载到内存中. 下面来看一下简单的例子: [java] view plain copy package com.loadclass.demo; import java.util.Dat

JVM类加载机制详解(二)类加载器与双亲委派模型

在上一篇JVM类加载机制详解(一)JVM类加载过程中说到,类加载机制的第一个阶段加载做的工作有: 1.通过一个类的全限定名(包名与类名)来获取定义此类的二进制字节流(Class文件).而获取的方式,可以通过jar包.war包.网络中获取.JSP文件生成等方式. 2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构.这里只是转化了数据结构,并未合并数据.(方法区就是用来存放已被加载的类信息,常量,静态变量,编译后的代码的运行时内存区域) 3.在内存中生成一个代表这个类的java.lan

Java调用SMSLib发送短信详解

项目中需要用到发送短信功能,之前没做过这方面,找人咨询了一下,也网上查了查,发现并不是很复杂.目前项目已经完成了,做个记录以备后用.程序中发送短信主要有4种方法: 1.向当地的运营商申请网关,不需要额外的设备,利用对方提供的 API调用程序发送短信,适用于大型的通信公司.稳定,速度快,适合短信量特别大的需求,需要连接到运营商的网络中,不适合内网项目. 2.短信猫发送短信,借助像 GSM MODEM之类的设备(支持AT指令的手机也行),通过数据线连接电脑来发送短信,这种方法比较适用于小公司及个人.

SpringMVC拦截器详解[附带源码分析]

目录 前言 重要接口及类介绍 源码分析 拦截器的配置 编写自定义的拦截器 总结 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:http://www.cnblogs.com/fangjian0423/p/springMVC-introduction.html 拦截器是每个Web框架必备的功能,也是个老生常谈的主题了. 本文将分析SpringMVC的拦截器功能是如何设计的,让读者了解该功能设计的原理. 重要接口及类介绍 1. Hand

spring--处理器拦截器详解——跟着开涛学SpringMVC

5.1.处理器拦截器简介 Spring Web MVC的处理器拦截器(如无特殊说明,下文所说的拦截器即处理器拦截器) 类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理.   5.1.1.常见应用场景 1.日志记录:记录请求信息的日志,以便进行信息监控.信息统计.计算PV(Page View)等. 2.权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面: 3.性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时