天天看点

Java反射简介、JDK动态代理实现、注解简介1. Java反射机制2. Class类3. Field类4. Method类5. Constructor类6. JDK动态代理7. 注解

Java反射、JDK动态代理、注解

  • 1. Java反射机制
    • 1.1 含义
    • 1.2 实现成员
  • 2. Class类
    • 2.1 实现
      • 2.1.1 对象名实现
      • 2.1.2 类名实现
      • 2.1.3 全限定名实现
  • 3. Field类
    • 3.1 实现指定属性
    • 3.2 实现所有属性
  • 4. Method类
    • 4.1 实现指定方法
    • 4.2 实现所有方法
  • 5. Constructor类
    • 5.1 实现
  • 6. JDK动态代理
    • 6.1 作用
    • 6.2 特点
    • 6.3 实例_优化连接池
  • 7. 注解
    • 7.1 作用
    • 7.2 类型
      • 7.2.1 元注解
      • 7.2.2 内置注解
      • 7.2.3 自定义注解
        • 7.2.3.1 实现
        • 7.2.3.2 ORM案例_使用注解将类信息转换成数据表格的SQL语句

1. Java反射机制

1.1 含义

通过Java反射机制,可以动态的访问、操作一个类的信息

1.2 实现成员

Java反射机制通过创建四种对象来实现

  1. Class类_字节码对象类
其实例为某个类的字节码
  1. Field类_属性类
其实例为某个类的属性
  1. Method类_方法类
其实例为某个类的方法
  1. Constructor类_构造方法类
其实例为某个类的构造方法

2. Class类

Class类可以创建某个类的字节码对象

要创建属性类、方法类、构造方法类的对象,需要先创建字节码对象类的对象

2.1 实现

2.1.1 对象名实现

public class Test {
    public static void main(String[] args){
        //创建Person类的对象
        Person person=new Person();
        //通过对象名创建Class对象
        Class class1=person.getClass();
    }
}
-------------------------------------------------------------
//Person类
class Person{
    private String name;
    private int age;
    //无参构造方法
    public Person(){
    }
    //有参构造方法
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    //learn方法-无参
    public void learn(){
        System.out.println(name+"在教室学习");
    }
    //learn方法-有参
    public void learn(String sub){
        System.out.println(name+"在教室学习"+sub);
    }
    //重写toString方法
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
     public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", 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;
    }
}
           

2.1.2 类名实现

public class Test {
    public static void main(String[] args){
        //通过类名创建Class对象
        Class class2=Person.class;
    }
}
           

2.1.3 全限定名实现

public class Test {
    public static void main(String[] args){
        //通过类名创建Class对象
        try {
            Class class3=Class.forName("cn.khue.csdn.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
           

3. Field类

3.1 实现指定属性

public class Test {
    public static void main(String[] args) throws Exception {
        //1.创建该类的字节码对象
        Class class3=Class.forName("cn.khue.csdn.Person");
        //2.创建该类的指定属性的对象
        Field fieldName=class3.getDeclaredField("name");
        //输出该属性对象的名称
        System.out.println(fieldName.getName());
        //输出该属性对象的类型
        System.out.println(fieldName.getType());
        //输出该属性对象的类型名称
        System.out.println(fieldName.getType().getName());
        //给该属性数值
        Person p=new Person();
        fieldName.setAccessible(true);//因为name属性为private,所以需要获取访问权限
        fieldName.set(p,"khue");//set需要先指定给哪一个对象的属性赋值,所以需要先创建Person类的对象
        System.out.println(p.getName());
    }
}
           

3.2 实现所有属性

public class Test {
    public static void main(String[] args) throws Exception {
        //1.创建该类的字节码对象
        Class class3=Class.forName("cn.khue.csdn.Person");
        //2.创建该类的指定属性的对象
        Field[] fields=class3.getDeclaredFields();
        //查看所有属性信息
        for(Field field:fields){
            System.out.print(field.getName()+"\t");//查看属性名
            System.out.println(field.getType());//查看属性类型
        }
    }
}
           

4. Method类

4.1 实现指定方法

public class Test {
    public static void main(String[] args) throws Exception {
        //1.创建该类的字节码对象
        Class class3=Class.forName("cn.khue.csdn.Person");
        //2.创建该类的指定方法的对象
        Method methodLearn=class3.getDeclaredMethod("learn");//无参方法
        Method methodLearn2=class3.getDeclaredMethod("learn",String.class);//有参方法
        //查看方法的信息
        System.out.println(methodLearn.getName());//打印方法名
        System.out.println(methodLearn2.getReturnType());//打印返回值类型
        System.out.println(methodLearn.getParameterCount());//打印形参个数
        System.out.println(Arrays.toString(methodLearn2.getParameterTypes()));//打印形参类型
        //调用方法
        Person person=new Person();
        Object obj=methodLearn.invoke(person);
        Object obj1=methodLearn2.invoke(person,"Java");
    }
}
           

4.2 实现所有方法

public class Test {
    public static void main(String[] args) throws Exception {
        //1.创建该类的字节码对象
        Class class3=Class.forName("cn.khue.csdn.Person");
        //2.创建该类所有方法的对象
        Method[] methods=class3.getDeclaredMethods();
        //查看方法的信息
        for(Method method:methods){
            System.out.print(method.getName()+"\t");//打印方法的名称
            System.out.print(method.getParameterCount()+"\t");//打印方法的形参个数
            System.out.print(Arrays.toString(method.getParameterTypes())+"\t");//打印方法的形参类型
            System.out.println(method.getReturnType());//打印方法的返回值类型
        }
    }
}
           

5. Constructor类

5.1 实现

public class Test {
    public static void main(String[] args) throws Exception {
        //1.创建该类的字节码对象
        Class class3=Class.forName("cn.khue.csdn.Person");
        //2.创建该类指定构造方法的对象
        Constructor constructor=class3.getDeclaredConstructor();//无参构造方法
        Constructor constructor1=class3.getDeclaredConstructor(String.class,int.class);//有参构造方法
        //3.创建所有构造方法
        Constructor[] constructors=class3.getConstructors();
    }
}
           

6. JDK动态代理

6.1 作用

在不修改被代理类源码的情况下,增强其功能

6.2 特点

  1. 面向接口

    只能增强接口中 被实现类实现的方法

    只能读取到接口中方法的注解

  2. 基于反射机制

6.3 实例_优化连接池

  1. 初始版本
public class ConnectionPool {
    private final static String URL;//数据库地址
    private final static String UNAME;//数据库登录用户名
    private final static String PWD;//数据库登录密码
    private final static int initSize;//连接池初始连接数量
    private final static int maxSize;//连接池最大连接数量
    private static LinkedList<Connection> pool;//存放连接的池
    //初始化连接池
    static{
        //获取驱动
        Class.forName("com.mysql.jdbc.Driver");
        //定义连接池
        pool=new LinkedList<Connection>();
        //创建连接并存放入池
        for(int i=0;i<initSize;i++){
            pool.add(initConnection());
        }
    }
    //创建一个连接
    public static Connection initConnection(){
        return DriverManager.getConnection(URL,UNAME,PWD);
    }
    //获取一个连接
    public static Connection getConnection(){
        if(pool.size()>0){
            return pool.removeFirst();//如果池中还有连接就直接取出
        }else{
            return initConnection();//如果池中没有连接就直接新建
        }
    }
    //归还连接
    public static void returnConnection(Connection ... conn){//可一次归还多个连接
        for(Connection c:conn){
            if(pool.size()<maxSize){
                pool.addLast(c);//如果连接池未满就直接入池
            }else{
                c.close();//如果连接池已满就之间关闭
            }
        }
    }
}
           
  1. 优化版本
public class ConnectionPool {
    private final static String URL;//数据库地址
    private final static String UNAME;//数据库登录用户名
    private final static String PWD;//数据库登录密码
    private final static int initSize;//连接池初始连接数量
    private final static int maxSize;//连接池最大连接数量
    private static LinkedList<Connection> pool;//存放连接的池
    //初始化连接池
    static{
        //获取驱动
        Class.forName("com.mysql.jdbc.Driver");
        //定义连接池
        pool=new LinkedList<Connection>();
        //创建连接并存放入池
        for(int i=0;i<initSize;i++){
            pool.add(initConnection());
        }
    }
    //创建一个连接
    public static Connection initConnection(){
        Connection connection=DriverManager.getConnection(URL,UNAME,PWD);
        //创建动态代理
        Connection proxyConnection=(Connection) Proxy.newProxyInstance(
                connection.getClass().getClassLoader(),//被代理类的类加载器
                connection.getClass().getInterfaces(),//被代理类所实现的接口
                new InvocationHandler() {//InvocationHandler的匿名内部类
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object obj=null;
                        if(method.getName().equals("close")){//如果调用了close方法,就直接执行连接回收方法
                            if(pool.size()<maxSize){
                                pool.addLast((Connection)proxy);
                            }else{
                                connection.close();
                            }
                        }else{//否则执行其它正常的方法
                            obj=method.invoke(connection,args);
                        }
                        return obj;
                    }
                }
        );
        return proxyConnection;
    }
    //获取一个连接
    public static Connection getConnection(){
        if(pool.size()>0){
            return pool.removeFirst();//如果池中还有连接就直接取出
        }else{
            return initConnection();//如果池中没有连接就直接新建
        }
    }
}
           

7. 注解

7.1 作用

  1. 生成文档
  2. 在编译时进行格式检查
  3. 替代配置文件gongn

7.2 类型

  1. 元注解
  2. 内置注解
  3. 自定义注解

7.2.1 元注解

元注解只能用于注解

  1. @Target

    用于限定注解的只用范围

@Target(ElementType.TYPE)//被使用的注解只能用于类
@Target(ElementType.FIELD)//被使用的注解只能用于属性
@Target(ElementType.METHOD)//被使用的注解只能用于方法
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})//被使用的注解可以用于类、属性、方法
...
           
  1. @Retention

    用于限定注解的生命周期

@Retention(RetentionPolicy.RUNTIME)//被使用的注解在运行时有效
@Retention(RetentionPolicy.CLASS)
@Retention(RetentionPolicy.SOURCE)
...
           
  1. @Documented
  2. @Inherited

7.2.2 内置注解

  1. @Override

    重写注解

  2. @Decprecated

    过时注解

  3. @SuressWarning

    抑制(关闭)警告注解

7.2.3 自定义注解

7.2.3.1 实现

@Target(限定范围)
@Retention(限定生命周期)
@interface 注解名{
	String value();//参数
	int age() default 25;//设定默认值的参数
	...
}
           

7.2.3.2 ORM案例_使用注解将类信息转换成数据表格的SQL语句

Object Relationship Mapping指对象关系映射

public class Test {
    public static void main(String[] args) throws Exception {
        //1.给定一个类的全限定名
        String str=generateSql("cn.khue.annotation2.Student");
        //2.输出该类的数据库表格创建的SQL语句
        System.out.println(str);
    }

    //给定类的全限定名,生成该类对应数据库表格的SQL语句
    public static String generateSql(String className) throws Exception {
        StringBuilder sb=new StringBuilder("create table ");
        //1.获取该类的字节码对象
        Class clazz=Class.forName(className);
        //2.获取该类的表名
        TableAnn ann=(TableAnn) clazz.getAnnotation(TableAnn.class);
        sb.append(ann.name()+"(");
        //3.获取该类的属性
        Field[] field=clazz.getDeclaredFields();
        for(int i=0;i<field.length;i++){
            FieldAnn fieldAnn=field[i].getAnnotation(FieldAnn.class);
            //字段名
            sb.append(field[i].getName()+" ");
            //字段类型
            sb.append(fieldAnn.type()+" ");
            //字段长度
            sb.append("("+fieldAnn.length()+") ");
            //字段约束
            sb.append(fieldAnn.constraint());
            //字段分隔
            if(i<field.length-1){
                sb.append(",");
            }
        }
        sb.append(")");
        return sb.toString();
    }
}

//学生类
@TableAnn(name = "student")
class Student{
    @FieldAnn(type = "int",length = 10,constraint = "primary key auto_increment")
    private int id;
    @FieldAnn(type = "varchar",length = 20,constraint = "not null unique")
    private String name;
    @FieldAnn(type = "int",length = 10,constraint = "not null")
    private int age;
}

//学生类注解
@Target(ElementType.TYPE)//限定注解用于类
@Retention(RetentionPolicy.RUNTIME)//限定注解在运行时有效
@interface TableAnn{
    String name();//表名
}

//学生属性注解
@Target(ElementType.FIELD)//限定注解用于属性
@Retention(RetentionPolicy.RUNTIME)//限定注解在运行时有效
@interface FieldAnn{
    String type();//字段类型
    int length();//字段类型长度
    String constraint() default "";//字段的约束
}
           

继续阅读