第17天(基础加强_注解_类加载器_动态代理)_学习目标版本

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第17天(基础加强_注解_类加载器_动态代理)_学习目标版本相关的知识,希望对你有一定的参考价值。

学习目标

  • 能够使用Junit进行单元测试
  • 能够说出注解的作用
  • 能够使用JDK提供的3个注解
  • 能够根据基本语法编写自定义注解实现类
  • 能够了解自定义注解解析
  • 能够了解元注解使用
  • 能够根据上课案例分析,编写模拟@Test案例
  • 能够理解动态代理原理
  • 能够使用动态代理Proxy编写代理类
  1. Junit单元测试

    1. Junit介绍

JUnit是一个Java语言的单元测试框架,简单理解为可以用于取代java的main方法。Junit属于第三方工具,一般情况下需要导入jar包,不过,多数Java开发环境已经集成了JUnit作为单元测试工具。

  1. Junit的使用

创建"MyJunit"java项目,并创建"com.itheima_00_Junit"包

技术分享

  • 编写测试类,简单理解Junit可以用于取代java的main方法
  • 在测试类方法上添加注解 @Test
  • @Test修饰的方法要求:public void 方法名() {…} ,方法名自定义建议test开头,没有参数。

    技术分享

  • 添加Eclipse中集成的Junit库,鼠标点击"@Test",使用快捷键"ctrl + 1",点击"Add Junit…"

    技术分享

    结果

    技术分享

  • 使用:选中方法右键,执行当前方法;选中类名右键,执行类中所有方法(方法必须标记@Test)

技术分享

  • 常用注解

    @Test,用于修饰需要执行的方法

    @Before,测试方法前执行的方法

    @After,测试方法后执行的方法

publicclass JunitDemo_1 {

    @Test

    publicvoidmyTest(){

        System.out.println("测试 test");

    }

    

    @Before

    publicvoidmyBefore(){

        System.out.println("方法前");

    }

    

    @After

    publicvoidmyAfter(){

        System.out.println("方法后");

    }

 

    /*运行结果:

     *    方法前

     *    测试 test

     *    方法后

     */

}

 

  • 常见使用错误,如果没有添加"@Test",使用"Junit Test"进行运行,将抛异常

技术分享

 

  1. 注解

    1. 注解概述

  • 什么是注解:Annotation注解,是一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次
    • 对比注释:注释是给开发人员阅读的,注解是给计算机提供相应信息的。
  • 注解的作用:
    • 编译检查:通过代码里标识注解,让编译器能够实现基本的编译检查。例如:@Override
    • 代码分析:通过代码里标识注解,对代码进行分析,从而达到取代xml目的。
    • 编写文档:通过代码里标识注解,辅助生成帮助文档对应的内容
  •  

 

  1. JDK提供的注解

  • @Deprecated 表示被修饰的方法已经过时。过时的方法不建议使用,但仍可以使用。
    • 一般被标记位过时的方法都存在不同的缺陷:1安全问题;2新的API取代
  • @Override JDK5.0表示复写父类的方法;jdk6.0 还可以表示实现接口的方法
  • @SuppressWarnings 表示抑制警告,被修饰的类或方法如果存在编译警告,将被编译器忽略

    deprecation ,或略过时

    rawtypes ,忽略类型安全

    unused ,忽略不使用

    unchecked ,忽略安全检查

    null,忽略空指针

serial, 忽略序列号

    all,忽略所有

 

  • @Deprecated

//#1 方法过期

class Parent1_1{

    @Deprecated

    public void init(){

        

    }

}

技术分享

 

  • @Override 复写父类方法

//#2.1 JDK5.0 复写父类方法

class Parent1_2{

    public void init(){

        

    }

}

class Son1_2 extends Parent1_2{

    @Override

    public void init() {

    }

}

 

  • @Override 实现接口方法

//#2.2 JDK6.0 实现父接口方法

interface Parent1_3{

    public void init();

}

class Son1_3 implements Parent1_3{

    @Override

    public void init() {

        

    }

}

 

  • @SupperssWarings

//#3 抑制警告

// serial : 实现序列号接口,但没有生产序列号

@SuppressWarnings("serial")

class Parent1_4 implements java.io.Serializable{

    

    //null :空指针

    @SuppressWarnings("null")

    public void init(){

        

        //rawtypes :类型安全,没有使用泛型

        //unused : 不使用

        @SuppressWarnings({ "rawtypes", "unused" })

        List list = new ArrayList();

          

        

        String str = null;

        

        str.toString();

        

    }

    

}

 

 

 

  1. 自定义注解:定义—基本语法

// #1 定义注解

@interface MyAnno1{

    

}

//#2 定义含有属性的注解

@interface MyAnno2{

    public String username() default "jack";

}

//#3 完整含属性注解

@interface MyAnno3{

    int age() default 1;

    String password();

    Class clazz();

    MyAnno2 myAnno(); // 注解

    Color color(); // 枚举

    String[] arrs();

}

enum Color{

    BLUE,RED;

}

 

  1. 自定义注解:使用

@MyAnno_1

@MyAnno_2(username="rose")

@MyAnno_3(

        age=18 ,

        password="1234" ,

        clazz=String.class ,

        myAnno=@MyAnno_2 ,

        color = Color.RED ,

        arrs = {"itcast","itheima"}

)

publicclass MyAnnoTest_4 {

 

}

 

  1. 自定义注解:解析

 

publicclass MyAnnoTest_5 {

    publicstaticvoid main(String[] args) {

booleanb = MyAnnoTest_4.class.isAnnotationPresent(MyAnno_1.class);

        System.out.println(b);    //false

    }

}

当运行上面程序后,我们希望输出结果是true,但实际是false。TestAnno2类上有@MyAnno1注解,但运行后不能获得,因为每一个自定义注解,需要使用JDK提供的元注解进行修饰才可以真正的使用。

 

  1. 自定义注解:定义—元注解

    技术分享

 

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@interface MyAnno1{

    

}

 

  1. 案例:自定义@Test

 

 

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

[email protected]MyAnno {

 

}

publicclass AnnotationDemo_0 {

    @MyAnno

    publicvoid demo1(){

        System.out.println("demo1执行了...");

    }

    @MyAnno

    publicvoid demo2(){

        System.out.println("demo2执行了...");

    }

    publicvoid demo3(){

        System.out.println("demo3执行了...");

    }

}

publicclass AnnotationTest_1 {

    publicstaticvoid main(String[] args) {

        try {

            //1.1 反射:获得类的字节码对象.Class

            Classclazz = AnnotationDemo_0.class;

            //1.2 获得实例对象

            Object obj = clazz.newInstance();

            

            //2 获得目标类所有的方法

            Method[] allMethod = clazz.getMethods();

            //3 遍历所有的方法

            for (Method method : allMethod) {

                //3.1 判断方法是否有MyTest注解

                booleanflag = method.isAnnotationPresent(MyAnno.class);

                if (flag) {

                    //4 如果有注解运行指定的类

                    method.invoke(obj, null);

                }

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        

        /* 输出结果:

         * demo1执行了...

         * demo2执行了...

         */

    }

}

    所有的类加载器都是 java.lang.ClassLoader 的子类

    技术分享

    全盘负责:A类如果要使用B类(不存在),A类加载器C必须负责加载B类。

        技术分享

    委托机制:A类加载器如果要加载资源B,必须询问父类加载是否加载。

        如果加载,将直接使用。

        如果没有机制,自己再加载。

java代理有jdk动态代理、cglib代理,这里只说下jdk动态代理,jdk动态代理主要使用的是java反射机制(既java.lang.reflect包)

  1. Proxy类

原理是(歌手、经纪人做例子):

 

 

动态代理:程序运行时,使用JDK提供工具类(Proxy),动态创建一个类,此类一般用于代理。

代理:你 -- 代理(增强) -- 厂商

代理类:目标类:被代理的

动态代理使用前提:必须有接口

 

Object proxyObj = Proxy.newProxyInstance(参数1,参数2,参数3);

参数1:ClassLoader,负责将动态创建类,加载到内存。当前类.class.getClassLoader();

参数2:Class[] interfaces ,代理类需要实现的所有接口(确定方法),被代理类实例.getClass().getInterfaces();

参数3:InvocationHandler, 请求处理类,代理类不具有任何功能,代理类的每一个方法执行时,调用处理类invoke方法。

voke(Object proxy ,Method ,Object[] args)

        参数1:代理实例

        参数2:当前执行的方法

        参数3:方法实际参数。

动态代理案例: 模拟Collections工具类的静态方法

技术分享

 

 

    @Test

    publicvoid test_2() {

        List<String>list = new ArrayList<String>();

        list.add("123");

        System.out.println(list.size());

        list = myProxy(list);

        list.set(0, "1");

        System.out.println(list.size());

    }

 

    publicstatic List<String> myProxy(List<String>list) {

 

        List<String>listProxy = (List) Proxy.newProxyInstance(

                ReflectTest.class.getClassLoader(), list.getClass()

                        .getInterfaces(), new MyPro(list));

        returnlistProxy;

 

publicclass MyPro implements InvocationHandler{

    private List<String>list ;

    public MyPro(List<String>list){

        this.list =list;

    }

    

    public Object invoke(Object porxy,Method method,Object[] arge) throws Exception{

        if("add".equals(method.getName()))

            thrownew UnsupportedOperationException("add NO");

        if("set".equals(method.getName()))

            thrownew UnsupportedOperationException("set NO");

        if("remove".equals(method.getName()))

            thrownew UnsupportedOperationException("remove NO");

        

        returnmethod.invoke(list, arge);

    }

}

 

@Test

    publicvoid test_2() {

        List<String>list = new ArrayList<String>();

        list.add("123");

        System.out.println(list.size());

        list = myProxy(list);

        list.set(0, "1");

        System.out.println(list.size());

    }

    publicstatic List<String> myProxy(final List<String>list) {

 

        List<String>list2= (List) Proxy.newProxyInstance(ReflectTest.class

.getClassLoader(), list.getClass().getInterfaces(),new InvocationHandler() {

    @Override

        public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {

        if ("add".equals(method.getName()))

            thrownew UnsupportedOperationException("add NO");

        if ("set".equals(method.getName()))

            thrownew UnsupportedOperationException("set NO");

        if ("remove".equals(method.getName()))

            thrownew UnsupportedOperationException("r NO");

            returnmethod.invoke(list, args);

                    }

                });

        returnlist2;

    }

以上是关于第17天(基础加强_注解_类加载器_动态代理)_学习目标版本的主要内容,如果未能解决你的问题,请参考以下文章

JAVAWEB学习笔记25_基础加强:类加载器注解 @xxx和动态代理

阶段1 语言基础+高级_1-3-Java语言高级_09-基础加强_第3节 注解_18_注解_案例_简单的测试框架

动态代理_基础版

基础加强

Java进阶学习第24天——动态代理与类加载器

包子学系列——Java基础第十五章_Java反射机制