hooyantsing's Blog

第107次课程_注解

字数统计: 1.7k阅读时长: 9 min
2020/02/16

源辰76班

第107次课程

2020.02.16

内容

注解

项目路径:****G:\YC74\200212_Mybatis动态SQL\code

1.反射机制

Movie.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package com.yc.mybatis.bean;
import java.util.Date;
public class Movie {
    private Integer id;
    private String name;
    private Integer duration;
    private Date releaseTime;
    private String foreignName;
    private String region;
    private String language;
    private String description;
    private String status;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name == null ? null :  name.trim();
    }
    public Integer getDuration() {
        return duration;
    }
    public void setDuration(Integer  duration) {
        this.duration = duration;
    }
    public Date getReleaseTime() {
        return releaseTime;
    }
    public void setReleaseTime(Date  releaseTime) {
        this.releaseTime = releaseTime;
    }
    public String getForeignName() {
        return foreignName;
    }
    public void setForeignName(String  foreignName) {
        this.foreignName = foreignName ==  null ? null : foreignName.trim();
    }
    public String getRegion() {
        return region;
    }
    public void setRegion(String region) {
        this.region = region == null ? null  : region.trim();
    }
    public String getLanguage() {
        return language;
    }
    public void setLanguage(String language)  {
        this.language = language == null ?  null : language.trim();
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String  description) {
        this.description = description ==  null ? null : description.trim();
    }
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status == null ? null  : status.trim();
    }
}

ReflectTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.yc.mybatis.dao;
import java.lang.reflect.*;
import com.yc.mybatis.bean.Movie;
public class ReflectTest {
    public static void main(String[] args)  throws Exception {
       Movie m = new Movie();
       
       //多态==>引用转型(父类指向子类对象)
       Object o = m;
       System.out.println(o==m);
       
       //通过反射来获取成员对象:属性、方法、构造函数、块、内部类
       
       //获取类对象:1、class 关键字;2、使用getClass();3、使用Class.forName()
       System.out.println(Movie.class);
       System.out.println(o.getClass());
       System.out.println(Class.forName("com.yc.mybatis.bean.Movie"));
       
       @SuppressWarnings("unchecked")
       //1.
       Class<Movie> cls = (Class<Movie>)  o.getClass();
       //2. Class<Movie> cls =  (Class<Movie>) m.getClass();
       //3. Class<Movie> cls = Movie.class;
       
       /*
        * 带Declared表示在当前类"定义"的属性、方法
        * 不带Declared表示是一个共有的属性、方法
        */
       
       //属性
       Field nameField =  cls.getDeclaredField("name");
       Field[] f2 =  cls.getDeclaredFields();
       //Field f3 = cls.getField("name");
       Field[] f4 = cls.getFields();
       
       //方法对象
       Method getNameMethod =  cls.getDeclaredMethod("getName");
       Method setNameMethod =  cls.getDeclaredMethod("setName",String.class);
       cls.getDeclaredMethods();
       cls.getMethod("setName",  String.class);
       cls.getMethods();
       
       //构造方法
       Constructor c1 =  cls.getConstructor();
       cls.getConstructors();
       cls.getDeclaredConstructor();
       cls.getDeclaredConstructors();
       
       System.out.println("==================获取设置属性、调用方法、构造函数创建对象==================");
       
       /*
        * 获取设置属性、调用方法、构造函数创建对象
        */
       
       //设置成员的可见性,临时将属性或方法设置为public可见
       nameField.setAccessible(true);
       nameField.set(m, "终结者6");
       Object nameValue = nameField.get(m);
       
       //执行方法
       setNameMethod.invoke(m, "少年派的奇幻旅行");
       //第二个参数 可变参数组
       nameValue = getNameMethod.invoke(m);
       
       
       System.out.println(nameValue);
    }
}

2.注解

注解.jpg

AnnotationTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.yc.mybatis.dao;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@MyAnno
public class AnnotationTest {
    @MyAnno
    String name;
    
    @MyAnno
    public void test() {
       
    }
    
    public static void main(String[] args) {
       MyAnno myanno =  AnnotationTest.class.getAnnotation(MyAnno.class);
       System.out.println(myanno);
       //用于测试@Inherited,注解是否对子类有效
       myanno =  SubAnnotationTest.class.getAnnotation(MyAnno.class);
       System.out.println(myanno);
    }
}

class SubAnnotationTest extends  AnnotationTest{
    
}

//---------------------------------------------------------------------------------

//定义注解<4个元注解>
//元注解:目标注解
//表示这个定义的注解可以加在哪些上面:FIELD加在属性上,METHOD加在方法上
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
//元注解:保持性:SOURSE源码有效 CLASS字节码有效 RUNTIME运行时有效
@Retention(RetentionPolicy.RUNTIME)
/*
* @Documented:默认情况下使用javadoc自动生成文档时,注解将被忽略掉
* 如果想在文档中也包含注解,必须使用Documented为文档注解
*/
/*
* @Inherited:表示该注解可以被子类继承
*/
@Inherited
@interface MyAnno{
    //定义name 属性 default 是默认选项
    public String name() default "test";
    
    //value 是缺省属性名,默认属性在只有一个属性值的情况下,可以在定义时不加value
    public String  value() default "";
    
    //注解数组属性,使用{}进行数组赋值,如果只有一个值,可以省略{}
    public String[] type() default {};
}

3.注解案例

模仿Junit类(@Before @Test @After)

Before.java

1
2
3
4
5
6
7
8
9
10
package com.yc.mybatis.junit;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Before {
}

Test.java

1
2
3
4
5
6
7
8
9
10
package com.yc.mybatis.junit;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}

After.java

1
2
3
4
5
6
7
8
9
10
package com.yc.mybatis.junit;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface After {
}

JunitDemo.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package com.yc.mybatis.junit;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import com.yc.mybatis.dao.HallMapperTest;
public class JunitDemo {
    /*
     * Test注解:表示该方式是一个测试的方法
     * Before注解:表示该方式是在被测试方法执行"前"执行的方法
     * After注解:表示该方式是在被测试方法执行"后"执行的方法
     *
     * 作业:
     * Junit测试结果:1、测试失败 2、测试错误
     */
    
    public static void main(String[] args) {
       Object obj = new HallMapperTest();
       
       JunitDemo jd = new JunitDemo();
       
       jd.testObject(obj);
    }
    
    public void testObject(Object obj) {
       if(obj == null) {
           return;
       }
       Class<?> cls = obj.getClass();
       //获取所有的共有方法
       Method[] methods = cls.getMethods();
       //将不同方法(Test、Before、After)放入各自集合中
       List<Method> tList = new  ArrayList<Method>();
       List<Method> bList = new  ArrayList<Method>();
       List<Method> aList = new  ArrayList<Method>();
       for(Method m : methods) {
           Test t =  m.getAnnotation(Test.class);
           if(t != null) {
               tList.add(m);
           }
           Before b =  m.getAnnotation(Before.class);
           if(b != null) {
               bList.add(m);
           }
           After a =  m.getAnnotation(After.class);
           if(b != null) {
               aList.add(m);
           }
       }
       
       int success = 0;
       int failure = 0;
       //启动测试:循环test方法集合
       for(Method m : tList) {
           //调动test方法,在执行前后,调用before方法和after方法
           try {
               //执行before方法
               for(Method bm : bList) {
                  try {
                      bm.invoke(obj);
                  } catch (Exception e) {
                      throw new  RuntimeException(e);
                  }
               }
               //执行test方法
               m.invoke(obj);
               //执行after方法
               for(Method am : aList) {
                  try {
                      am.invoke(obj);
                  } catch (Exception e) {
                      throw new  RuntimeException(e);
                  }
               }
               success++;
           } catch (Exception e) {
               e.printStackTrace();
               failure++;
           }
       }
       
       //运行通过,没有异常,统计正确,出现异常则错误数加一
       System.out.println("测试通过方法数量:" + success);
       System.out.println("测试失败方法数量:" + failure);
    }
}

测试目标:

HallMapperTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.yc.mybatis.dao;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Assert;

import com.yc.mybatis.bean.Cinema;
import com.yc.mybatis.bean.Hall;
import com.yc.mybatis.junit.*;

public class HallMapperTest {
    private SqlSession session;
    
    @Before
    public void before() throws IOException {
        // 定义mybatis配置文件路径,默认从classpath开始
        String resource = "mybatis.xml";
        // 读入配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 创建会话工厂bean
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // MyBatis的会话底层包装一个JDBC连接
        session = sqlSessionFactory.openSession();
    
    }
    
    
    
    @Test
    public void SelectAll() {
        HallMapper hm = session.getMapper(HallMapper.class);
        Hall h = hm.selectById(1);
        
        Assert.assertEquals("3号厅", h.getName());        
        Assert.assertEquals("2D", h.getHallType());
    }
    
    @Test
    public void text() {
        CinemaMapper cm = session.getMapper(CinemaMapper.class);
        Cinema c = cm.selectById(4);
        List<Hall> halls = c.getHalls();
        
        Assert.assertEquals(4, halls.size());    
        Assert.assertEquals("3号厅", halls.get(0).getName());    
    }
    
}
CATALOG