注解与反射

注解与反射

1注解

1.什么是注解?

  • 注解是JDK5.0开始引入的新技术
  • 注解的作用:不是程序本身可以对程序作出解析,可以被其他程序读取
  • 注解格式:注解是" @注释名 "在代码中存在的,还可以添加一些参数值

2.内置注解

  • @Override:定义在java.lang.Override中,只是用与修饰方法 ,子类继承父类的时候重写方法,就会被看到这个注解
  • @Deprecated: 定义在java.lang.Deprecated中,用于修辞方法,属性,类。
  • @SuppressWarnings : java.lang SuppressWarnings中用来抑制编译时的警告信息: @SuppressWarnings(“all”), @SuppressWarnings(“unchecked”) , @SuppressWarnings(value={“unchecked” “deprecation”})

3.元注解

  • @Target:b表示注解作用的地方,比如类,方法,成员变量,接口等,参数是一个枚举类型数组
  • @Retention: 表示需要再什么级别保存注解,描述注解声明周期(SOURCE<CLASS<RUNTIME)表示存活的运行周期,一般来说都是RUNTIME
常用的元注解 
@Target 
     作用:用来标识注解使用的位置,如果没有使用该注解标识,则自定义的注解可以使用在任意位置。 * 可使用的值定义在ElementType枚举类中,常用值如下 
     TYPE,类,接口 
     FIELD, 成员变量
     METHOD, 成员方法
     PARAMETER, 方法参数 
     CONSTRUCTOR, 构造方法
     LOCAL_VARIABLE, 局部变量
 @Retention * 作用:用来标识注解的生命周期(有效范围) * 可使用的值定义在RetentionPolicy枚举类中,
 常用值如下 
      SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在 
      CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值 
      RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段

4.自定义注解

  1. 自定义格式代码如下:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Classname{
        String value();
    }
    
    //属性注解
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Attribute{
        String colmuNmae();
        String type();
        int length();
    
    }
    

5.注解解析

1.定义注解

package com.xjggb;

public @interface Book {
    String value();
    double price() default 100;  //默认值
    String[] authros();
}

2.类的使用

package com.xjggb.entity;

import com.xjggb.Book;

@Book(value = "红楼梦",authros = {"曹雪芹"})
public class BookShelf {
    @Book(value = "西游记",authros = {"吴承恩","白求恩"},price = 200)
    public void showBook(){

    }
}

3.解析

package com.xjggb.text;

import com.xjggb.Book;

import java.lang.reflect.Method;
import java.util.Arrays;

public class Demo05 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
/** 什么是注解解析 * 使用Java技术获得注解上数据的过程则称为注解解析。 与注解解析相关的接口
 * * Annotation: 注解类,该类是所有注解的父类。
 * * AnnotatedElement:该接口定义了与注解解析相关的方法 T getAnnotation(Class<T> annotationClass) 根据注解类型获得对应注解对象 Annotation[] getAnnotations() *
 * 获得当前对象上使用的所有注解,返回注解数组,包含父类继承的 Annotation[] getDeclaredAnnotations()
 * * 获得当前对象上使用的所有注解,返回注解数组,只包含本类的 boolean isAnnotationPresent(Class<Annotation> annotationClass)
 * * 判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false 获取注解数据的原理
 * * 注解作用在哪个成员上就会得该成员对应的对象来获得注解
 * * 比如注解作用成员方法,则要获得该成员方法对应的Method对象
 * * 比如注解作用在类上,则要该类的Class对象
 * * 比如注解作用在成员变量上,则要获得该成员变量对应的Field对象。
 * * Field,Method,Constructor,Class等类都是实现了AnnotatedElement接口 */

        Class<?> aClass = Class.forName("com.xjggb.entity.BookShelf");

        //判断类上是否有注解
        if (aClass.isAnnotationPresent(Book.class)) {
            Book annotation = aClass.getAnnotation(Book.class);
            // 获得书名
            System.out.println(annotation.value());
            // 获得作者
            System.out.println(Arrays.toString(annotation.authros()));
            // 获得价格
            System.out.println(annotation.price());


        }

        Method showBook = aClass.getMethod("showBook");
        Book annotation = showBook.getAnnotation(Book.class);
        System.out.println("annotation.value() = " + annotation.value());


    }
}

6.注解案例

模拟Junit测试的@Test

3.6.2 案例分析

  1. 模拟Junit测试的注释@Test,首先需要编写自定义注解@MyTest,并添加元注解,保证自定义注解只能修饰方

法,且在运行时可以获得。

  1. 然后编写目标类(测试类),然后给目标方法(测试方法)使用 @MyTest注解,编写三个方法,其中两个加上

@MyTest注解。

  1. 最后编写调用类,使用main方法调用目标类,模拟Junit的运行,只要有@MyTest注释的方法都会运行。

代码如下

package com.xjggb.text;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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



class TestMyTest{
    @MyTest
    public void tests01(){
        System.out.println("来了哦老弟");
    }

    public void tests02(){
        System.out.println("test02");
    }

    @MyTest
    public void tests03(){
        System.out.println("来了来了");
    }








}

测试代码

package com.xjggb.text;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Demo06 {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class<?> aClass = Class.forName("com.xjggb.text.TestMyTest");

        Object o = aClass.newInstance();



        //获取所有的成员方法
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {

            if (method.isAnnotationPresent(MyTest.class)) {
                //调用方法
                method.invoke(o);
            }

        }

    }
}

7.反射机制

1.反射机制提供的功能:

  • 在运行是判断任意一个对象的所属类
  • 在运行是构造任意一个类的对象
  • 在运行时获取泛型的信息
  • 在运行是调用任意一个对象的成员变量和方法
  • 在运行是处理注解
  • 生成动态代理

2.JAVA反射的优点:

  • 优点:可以实现动态创建对象和编译,体现出很大的灵活性
  • 缺点:对性能有影响,使用反射就是告诉jvm,我们能我们需要什么,而jvm能满足我们什么,这些操作跟直接操作相比会慢一些

3.java反射的主要API:

  • java.lang.Class:代表一个类
  • java.lang.reflect.Field:代表类的成员变量
  • java.lang.reflect.Method:代表类的方法
  • java.lang.reflect.Constructor:代表类的构造器

4.Class类

  • Class本身也是一个类
  • 一个加载的类在jvm中只会有一个Class实例
  • 一个Class对应的是一个加载到JVM中的class文件
  • 通过Class可以完整的得到一个类中的所有被加载的结构
  • 每个类的实例都会记得自己是由哪个Class实例锁生成

反射的概念

反射是一种机制,利用该机制可以在程序运行过程中对类进行解剖并操作类中的所有成员(成员变量,成员方法,构造方法)

5.获取Class实例三种方法

实体类

class Student{
    private long id;
    private String name;
    private int age;
    //无参构造
    public Student(){}

    //有参构造
    public Student(Long id,String name,int age){
        this.id=id;
        this.name=name;
        this.age=age;
    }
//提供对外访问get()

    public long getId(){
        return id;
    }
    public String getName(){
        return name;
    }
    public int getAge(){
        return age;
    }

    //提供对外访问set()方法
    public void setId(long id){
        this.id=id;
    }
    //提供对外访问set()方法
    public void setName(String name){
        this.name=name;
    }
    //提供对外访问set()方法
    public void setAge(int age){
        this.age=age;
    }

代码如下:

public class Test01 {

    public static void main(String[] args) throws ClassNotFoundException {

   //创建Students实例对象
        Student student = new Student();

   /*
   * 第一种,知道类的全名,且该类的的路径下,可以通过Class类的静态方法forName()获取,可抛出ClassNotFoundException
   * */
        Class c = Class.forName("com.entity.Student");
        System.out.println("c = " + c.hashCode());

  /*
  * 第二种 知道某个类的实例,调用该实例的getClass()方法获取Class对象
  * */
        Class c2 = student.getClass();
        System.out.println("c2 = " + c2.hashCode());

  /*
  * 第三种  若知道具体的类,通过class属性获取,该方法最为安全可靠,程序性能最高
  * */
        
        Class c3 = Student.class;
        System.out.println("c3 = " + c3.hashCode());
    }
}




}

6.Class常用的方法

String getSimpleName(); 获得类名字符串:类名

String getName(); 获得类全名:包名+类名

T newInstance() ; 创建Class对象关联类的对象

代码如下

package com.xjggb.text;

import com.xjggb.entity.Student;

public class Demo02 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {

        //后的Class对象
        Class<Student> studentClass = Student.class;

        //获取类全名  包名+类名
        System.out.println("获取类全名" + studentClass.getName());
        //获取类名
        System.out.println("获取类名" + studentClass.getSimpleName());

        //创建对象
        Student student = studentClass.newInstance();

        System.out.println("创建对象"+student);


    }
}

7.反射操作构造方法

1.概述

  1. 反射操作构造方法的目的:获得Constructor对象来创建类的对象。
  2. Constructor类概述 :类中的每一个构造方法都是一个Constructor类的对象

2.Class类中与Constructor相关的的方法

1. Constructor getConstructor(Class... parameterTypes) 
         * 根据参数类型获得对应的Constructor对象。 
         * 只能获得public修饰的构造方法 
2. Constructor getDeclaredConstructor(Class... parameterTypes) 
          * 根据参数类型获得对应的Constructor对象,包括private
3. Constructor[] getConstructors() 
          *获得类中的所有构造方法对象,只能获得public4. Constructor[] getDeclaredConstructors()
          *获得类中的所有构造方法对象,包括private修饰的

3.Constructor对象常用方法

1. T newInstance(Object... initargs) 
       *根据指定的参数创建对象 
2. void setAccessible(true) 
      *设置是否取消权限检查,true取消权限检查,false表示不取消(暴力反射)

实体类

package com.xjggb.entity;

public class User {
    private String name;
    private String sex;
    private int age;

    public User() {
    }

    public User(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
    private User(String name, String sex) {
        this.name = name;
        this.sex = sex;

    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return sex
     */
    public String getSex() {
        return sex;
    }

    /**
     * 设置
     * @param sex
     */
    public void setSex(String sex) {
        this.sex = sex;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "User{name = " + name + ", sex = " + sex + ", age = " + age + "}";
    }
}

代码如下:

package com.xjggb.text;

import com.xjggb.entity.Student;
import com.xjggb.entity.User;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Demo02 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        //后的Class对象
        Class<User> studentClass = User.class;

       //获取类中的所有public构造方法
        Constructor<?>[] constructors = studentClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            //System.out.println("类中所有的构造方法" + constructor);
        }

        //获取所有的私有private构造方法
        Constructor<?>[] declaredConstructors = studentClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
           // System.out.println("类中所有私有构造方法" + declaredConstructor);

        }

        //根据参数类型获取Constructor
       // Constructor<User> constructor = studentClass.getDeclaredConstructor(String.class);
       // System.out.println("根据参数类型获取" + constructor);

        Constructor<User> constructor1 = studentClass.getConstructor(String.class,String.class,int.class);
       // System.out.println("根据参数类型获取1 = " + constructor1);



        //通过私有有参构造创建对象
        Constructor<User> declaredConstructor = studentClass.getDeclaredConstructor(String.class, String.class);

        //会报错  IllegalAccessException   添加
        declaredConstructor.setAccessible(true);  //取消权限检查(暴力反射)

        //获取对象
        User user = declaredConstructor.newInstance("来了老弟", "男");
        System.out.println("user = " + user);


        //通过无参构造创建对象
        Constructor<User> constructor = studentClass.getConstructor();
        User user1 = constructor.newInstance();
        System.out.println("user1 = " + user1);


        Constructor<User> constructor2 = studentClass.getConstructor(String.class, String.class, int.class);

        User user2 = constructor2.newInstance("来了老弟", "男", 123);
        System.out.println("user2 = " + user2);



    }
}

8.反射操作成员方法

  1. Method类概述
反射之操作成员方法的目的
        * 操作Method对象来调用成员方法 
Method类概述 
       * 每一个成员方法都是一个Method类的对象。

2.Class类中与Method相关的方法

Method getMethod(String name,Class...args); 
     * 根据方法名和参数类型获得对应的构造方法对象,只能获得public的 
Method getDeclaredMethod(String name,Class...args);
    * 根据方法名和参数类型获得对应的构造方法对象,包括private的 
Method[] getMethods();
    * 获得类中的所有成员方法对象,返回数组,只能获得public修饰的且包含父类的  Method[] getDeclaredMethods(); 
    * 获得类中的所有成员方法对象,返回数组,只获得本类的,包含private修饰的
  1. Method对象常用方法
Object invoke(Object obj, Object... args)
     * 调用指定对象obj的该方法 * args:调用方法时传递的参数 
void setAccessible(true) 设置是否取消权限检查,true取消权限检查,false表示不取消(暴力反射)

代码如下

package com.xjggb.text;

import com.xjggb.entity.User;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Demo03 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {

        //获取Class对象
        Class<?> name = Class.forName("com.xjggb.entity.User");

        //实例化
        User user = (User) name.newInstance();


        show4(name,user);


    }

    // 获得类中的所有成员方法对象,返回数组,只获得本类的,包含private修饰的
    public static void show4(Class name, User user){

        Method[] declaredMethods = name.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("declaredMethod = " + declaredMethod);
        }

    }

    // 获得类中的所有成员方法对象,返回数组,只能获得public修饰的且包含父类的
    public static void show3(Class name, User user){
        Method[] methods = name.getMethods();

        for (Method method : methods) {
            System.out.println("method = " + method);

        }

    }

    //获取private方法
    public static void show2(Class name, User user) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {


        Method show1 = name.getDeclaredMethod("show1",String.class);

        //暴力反射
        show1.setAccessible(true);

        Object invoke1 = show1.invoke(user,"来了老弟");
    }


    //获取public
    //获取setName方法对应的Method对象
    public static void show1(Class name, User user) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {


        Method setName = name.getMethod("setName",String.class);
        //参数user参数实例化
        Object invoke = setName.invoke(user,"来了老弟");
        System.out.println("invoke = " + invoke);
    }
}

9.反射操作成员变量

1.概述

反射之操作成员变量的目的 
    * 通过Field对象给对应的成员变量赋值和取值
Field类概述 
   * 每一个成员变量都是一个Field类的对象。

2.Class类中与Field相关的方法

Field getField(String name); 
        * 根据成员变量名获得对应Field对象,只能获得public修饰 
Field getDeclaredField(String name); 
       * 根据成员变量名获得对应Field对象,包含private修饰的 
Field[] getFields(); 
     * 获得所有的成员变量对应的Field对象,只能获得public的 
Field[] getDeclaredFields(); 
    * 获得所有的成员变量对应的Field对象,包含private的

3.Field对象常用方法

void set(Object obj, Object value) 
void setInt(Object obj, int i) 
void setLong(Object obj, long l)
void setBoolean(Object obj, boolean z) 
void setDouble(Object obj, double d)


Object get(Object obj) int getInt(Object obj) 
long getLong(Object obj) 
boolean getBoolean(Object ob)
double getDouble(Object obj)

4.权限开启

void setAccessible(true);暴力反射,设置为可以直接访问私有类型的属性。 
Class getType(); 获取属性的类型,返回Class对象。

代码如下

package com.xjggb.text;

import com.xjggb.entity.User;

import java.lang.reflect.Field;

public class Demo04 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {

        //获取Class对象
        Class<?> name = Class.forName("com.xjggb.entity.User");
        //实例化
        User user = (User) name.newInstance();
     show6(name,user);


    }

    //给private成员变量赋值
    public static void show6(Class name, User user) throws NoSuchFieldException, IllegalAccessException {

        Field name1 = name.getDeclaredField("name");
        //开启暴力反射

        name1.setAccessible(true);
        //给指定表的user对象赋值  来了老弟
        name1.set(user,"来了老弟");


       //获取指定表的对象user 成员变量name的值
        System.out.println("name1.get(user) = " + name1.get(user));



    }

    //给public成员变量赋值
    public static void show5(Class name, User user) throws NoSuchFieldException, IllegalAccessException {

        //给public成员变量赋值
        Field password = name.getField("password");
        //给指定表的user对象赋值  123
        password.set(user,123);

        //获取指定表的对象user 成员变量password的值
        System.out.println("password.get(user) = " + password.get(user));

    }


    
    
    //根据成员变量名获得对应Field对象,包含private修饰的
    public static void show4(Class name, User user) throws NoSuchFieldException {
        Field name1 = name.getDeclaredField("name");
        System.out.println("name1 = " + name1);


    }
    

    //根据成员变量名获得对应Field对象,只能获得public修饰
    public static void show3(Class name, User user) throws NoSuchFieldException {

        Field password = name.getField("password");
        System.out.println("password = " + password);


    }


     //获得所有的成员变量对应的Field对象,包含private的
    public static void show2(Class name, User user){

        Field[] declaredFields = name.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("declaredField = " + declaredField);
        }

    }


    //获得所有的成员变量对应的Field对象,只能获得public的
    public static void show1(Class name, User user){
        Field[] fields = name.getFields();
        for (Field field : fields) {
            System.out.println("field = " + field);
        }



    }



}

7.反射性能测试

代码如下:

public class Test02 {
    //    反射调用
   public static void Test04() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
       //获取Class
       Class c= Class.forName("com.entity.Student");
//        构建Student对象
       Student student = (Student)c.newInstance();
//获取指定方法
       Method getName = c.getDeclaredMethod("getName", null);
//        开始时间
       long l = System.currentTimeMillis();
       for (int i = 0; i < 100000; i++) {
           getName.invoke(student,null);
       }
       long l1 = System.currentTimeMillis();
       System.out.println("反射调用执行100000 需要的时间" + (l1-l)+"ms");
   }
   
//    普通方式调用
    public static void Test01(){
        Student student = new Student();
//        开始调用时间
        long l = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            student.getName();
        }
//     100000次疯狂循环调用后的时间
        long l1 = System.currentTimeMillis();
        System.out.println(" 普通范式执行100000次所需要的的时间"+(l1-l)+"ms" );
    }
    
//    关闭检测反射调用
    public static void Test03() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//获取Class对象
        Class c = Class.forName("com.entity.Student");

//        构建Student对象
        Student student = (Student) c.newInstance();

        Method getName = c.getDeclaredMethod("getName", null);
//        关闭检测
        getName.setAccessible(true);
//        开始执行时间
        long l = System.currentTimeMillis();

        for (int i = 0; i <100000 ; i++) {

            getName.invoke(student,null);
        }
//        执行后的的时间
        long l1 = System.currentTimeMillis();
        System.out.println("反射调用,关闭检测执行100000需要" + (l1-l)+"ms");
        
    }

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Test01();//    普通方式调用
        Test03();//    关闭检测反射调用
        Test04(); //    反射调用    
        /*
        *  普通范式执行100000次所需要的的时间2ms
        * 反射调用,关闭检测执行100000需要6ms
        * 反射调用执行100000 需要的时间40ms
        * */
    }
    
}

6.反射操作注解

代码如下:

package com.text;
import java.lang.annotation.*;
import java.lang.reflect.Field;

public class Text04 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {

        Class c = Class.forName("com.text.Student2");

//        获取类的注解
        Classname tablelong = (Classname) c.getAnnotation(Classname.class);
        String value = tablelong.value();
        System.out.println("value = " + value);
//        获取类字段的注解
//获取属性名称
        Field name = c.getDeclaredField("name");
//       获取属性注解
        Attribute annotation = name.getAnnotation(Attribute.class);
        System.out.println("annotation.colmuNmae() = " + annotation.colmuNmae());
        System.out.println("annotation.colmuNmae() = " + annotation.type());
        System.out.println("annotation.colmuNmae() = " + annotation.length());
    }


}

@Classname("db_student")
class Student2{
    @Attribute(colmuNmae = "db_id",type = "int",length = 10)
 private int id;
    @Attribute(colmuNmae = "db_age",type = "int",length = 10)
 private int age;
    @Attribute(colmuNmae = "db_name",type = "int",length = 10)
 private String  name;


    public Student2() {
    }

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

    /**
     * 获取
     * @return id
     */
    public int getId() {
        return id;
    }

    /**
     * 设置
     * @param id
     */
    public void setId(int id) {
        this.id = id;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return "Student2{id = " + id + ", age = " + age + ", name = " + name + "}";
    }
}



//类名的注解
@Target(ElementType.TYPE) //作用在类上
@Retention(RetentionPolicy.RUNTIME)
@interface Classname{
    String value();
}

//属性注解
@Target(ElementType.FIELD)  //该注解只能在属性上
@Retention(RetentionPolicy.RUNTIME)
@interface Attribute{
    String colmuNmae();
    String type();
    int length();

}



7.动态代理

  1. 动态代理:想给某个接口的类种方法,加一些而外的处理,比如日志,事务等。可以给这个类创建一个代理,就是创建一个新的类,这个类不仅包含类的方法的功能,而且还在原来的基础上添加而外处理的新类,这个代理类并不是定义好的,是动态生成的,具有解耦意义,灵活,扩展性强
  2. 动态代理实现:首先必须定义一个接口,还要有一个InvocationHandler(将实现接口的类的对象传递给它)处理类。再有一个工具类Proxy(习惯性将其称为代理类,因为调用他的newInstance()可以产生代理对象,其实他只是一个产生代理对象的工具类)。利用到InvocationHandler,拼接代理类源码,将其编译生成代理类的二进制码,利用加载器加载,并将其实例化产生代理对象,最后返回。
  3. 动态代理应用:Spring的AOP,加事务,加权限,加日志
1.jdk动态代理代码如下:

1.创建接口:

public interface Student {
    public void rent();
}

2.实现接口:

public class StudentImpe implements Student {

    @Override
    public void rent() {
        System.out.println("我是行健乖乖霸");
    }
}

3.创建类实现:InvocationHandler接口

public class ProxyInvocationHandler implements InvocationHandler {
//定义Object类
private Object object;

//给Object类赋值
public void setObject(Object object){
    this.object=object;
}

//代理类
    public Object getProxy() {
        return Proxy.newProxyInstance(
                this.getClass().getClassLoader(),  //获取当前类的Class加载文件
                object.getClass().getInterfaces(), //加载类的接口
                this); //
    }
//    重学invoke方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//    争抢方法
    log(method.getName());

        Object invoke = method.invoke(object);

        return invoke;
    }

//    自定义增强方法
    public void log(String methodName){
    System.out.println("执行了"+methodName+"方法");
    }

}

4.测试

public class Text04 {
    public static void main(String[] args) {

        StudentImpe test03 = new StudentImpe();

        ProxyInvocationHandler proxy= new ProxyInvocationHandler();
        //传入对象
        proxy.setObject(test03);
//        获取代理对象
        Student proxy1 = (Student) proxy.getProxy();
//        调用方法
        proxy1.rent();    
    }
}
2.cglib动态代理代码如下:
public class Student {

    public void eat(){
    System.out.println("我是兴建乖乖霸");
    }

}



class CglibProxy implements MethodInterceptor{

    private Object target; //创建代理对象

    public Object getInterce(Object target){

        this.target=target;

        Enhancer enhancer = new Enhancer();
//        设置父类为实例

        enhancer.setSuperclass(this.target.getClass());
//        回调方法
        enhancer.setCallback(this);

//        创建代理对象
        return enhancer.create();
    }


    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        System.out.println(" 调用前" );
        show();
        Object o1 = methodProxy.invokeSuper(o, objects);//执行方法的调用
        System.out.println(" 调用后" );


        return o1;
    }
//    自定义增强方法
    public void show(){
    System.out.println("执行了自定义增强方法");
    }





    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();

        Student panda = new Student();
        Student interce = (Student) proxy.getInterce(panda);
       interce.eat();

    }


}

8.总结

  1. 对注解的熟悉了解和自定义编写注解
  2. 反射的创建方式 有三种
  3. 通过反射创建构造方法 通过构造方法创建对象
  4. 通过反射操作方法
  5. 通过反射操作成员变量
  6. 通过反射操作注解
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值