反射,动态代理随笔

反射的基本概述

  • 一个class文件被加载到内存的时候,JVM就会经行解剖,把这个class文件的所有成员全部解剖出来,然后JVM会创建一个Class对象,把这些成员信息全部都封装起来,所谓反射就是指:我们获取到这个Class对象,就相当于获取到了该类的所有成员信息,我们就能操又该类的所有成员.
  • Java反射机制是在运行状态中,对于任意一个类,都能够知道这类的所有属性和方法;
  • 对于任意一个对象,都能够调用它的任意一个方法和属性;
  • 这种动态获取的细心以及动态调用它的任意一个方法和属性;
  • 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.
  • 要想解剖一个类,必须要获取到该类的字节码文件对象.

获取Class对象的三种方式

  • 通过Class.forName()方法获取:

static Class<?>


forName(String className)

返回与带有给定字符串名的类或接口相关联的 Class 对象。

className--完整类名,eg:com.test.Test01

  • 通过类名直接获取Class对象:

    eg: Class clazz=Person.class;

  • 通过对象获取Class对象:

    eg:Class clazz=new Person().getClass();

  • 写程序的阶段

    • 三种方式

Object类的getClass(类的完整类名)方法


读取配置文件,判断两个对象是否是同一个字节码文件


静态属性class(锁对象)


当作静态方法的锁对象


Class类中静态方法forName()


读取配置文件, 判断是否是同一个字节码对象

  • 代码案例

    ?

    1 ? package com.heima.reflect;

    2                  import com.heima.bean.Person;

    3

    4                  public class Demo1_Reflect {

    5

    6                          /**

    7                           * @param args

    8                           * @throws ClassNotFoundException

    9                           */

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

    11                                  Class clazz1 = Class.forName("");

    12                                  // 接口 a = 实现类的对象 a.方法

    13                                  //方式一

    14                                  Class clazz2 = Person.class;

    15                                  //方式二

    16                                  Person p = new Person();

    17                                  Class clazz3 = p.getClass();

    18                                  //方式三

    19                                  System.out.println(clazz1 == clazz2);

    20                                  System.out.println(clazz2 == clazz3);

    21                          }

    22

  1. }
  • Class.forName()读取配置文件_代码示例

    1 ?package com.heima.reflect;

    2

    3 import java.io.BufferedReader;

    4 import java.io.FileReader;

    5

    6 public class Demo2_Reflect {

    7

    8         /**

    9          * * 榨汁机(Juicer)榨汁的案例

    10          * 分别有水果(Fruit)苹果(Apple)香蕉(Banana)桔子(Orange)榨汁(squeeze)

    11          * @throws IOException

    12          */

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

    14                 Juicer j = new Juicer();                                                                        //创建榨汁机

    15                 //j.run(new Apple());

    16                 //j.run(new Orange());

    17                 BufferedReader br = new BufferedReader(new FileReader("config.properties"));//com.heima.reflect.Apple

    18                 Class clazz = Class.forName(br.readLine());                                        //获取该类的字节码文件

    19                 Fruit f = (Fruit) clazz.newInstance();                                                //创建实例对象

    20

    21                 j.run(f);

    22         }

    23 }

    24 interface Fruit {

    25         public
    void squeeze();

    26 }

    27 class Apple implements Fruit {

    28         public
    void squeeze() {

    29                 System.out.println("榨出一杯苹果汁儿");

    30         }

    31 }

    32

    33 class Orange implements Fruit {

    34         public
    void squeeze() {

    35                 System.out.println("榨出一杯橘子汁儿");

    36         }

    37 }

    38

    39 class Juicer {

    40         /*public void run(Apple a) {

    41                 a.squeeze();

    42         }

    43

    44         public void run(Orange o) {

    45                 o.squeeze();

    46         }*/

    47

    48         public
    void run(Fruit f) {

    49                 f.squeeze();

    50         }

    51

    52 }

通过反射获取构造函数_Constructor

  • 成员方法

T


newInstance()

创建此 Class 对象所表示的类的一个新实例。


Constructor<T>


getConstructor(Class<?>... parameterTypes)

返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。


Constructor<?>[]


getConstructors()

返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。


Constructor<T>


getDeclaredConstructor(Class<?>... parameterTypes)

返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。


Constructor<?>[]


getDeclaredConstructors()

返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法

  • 创建对象_代码示例

通过反射获取成员变量_Field

  • 成员方法

    • Class类

Field


getField(String name)

返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。


Field[]


getFields()

返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。


Field


getDeclaredField(String name)

返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。


Field[]


getDeclaredFields()

返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。

  • Field类

void


setAccessible(boolean flag)

将此对象的 accessible 标志设置为指示的布尔值。


void


set(Object obj, Object value)

将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

  • 调用方法_代码示例

通过反射获取成员方法_Method

  • Class类

Method


getMethod(String name, Class<?>... parameterTypes)

返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。


Method[]


getMethods()

返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。


Method


getDeclaredMethod(String name, Class<?>... parameterTypes)

返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。


Method[]


getDeclaredMethods()

返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

  • Method类

Object


invoke(Object obj, Object... args)

对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。

  • 案例

通过反射越过泛型检查

  • 需求:ArrayList的一个对象,在这个集合中添加一个字符串数据,如何实现呢?
  • 泛型只在编译期有效,在运行期会被擦除掉.
  • 代码示例

    1 ?package com.heima.test;

    2

    3 import java.lang.reflect.Method;

    4 import java.util.ArrayList;

    5

    6 public class Test1 {

    7

    8         /**

    9          * @param args

    10          * ArrayList<Integer>的一个对象,在这个集合中添加一个字符串数据,如何实现呢?

    11          * 泛型只在编译期有效,在运行期会被擦除掉

    12          * @throws Exception

    13          */

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

    15                 ArrayList<Integer> list = new ArrayList<>();

    16                 list.add(111);

    17                 list.add(222);

    18

    19                 Class clazz = Class.forName("java.util.ArrayList");                                //获取字节码对象

    20                 Method m = clazz.getMethod("add", Object.class);                                //获取add方法

    21                 m.invoke(list, "abc");

    22

    23                 System.out.println(list);

    24

    25         }

    26

    27 }

动态代理的概述和实现

  1. 动态代理:在程序运行过程中产生的这个对象,而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理
  2. 在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib,Proxy类中的方法创建动态代理类对象.
  3. 成员方法

    1. proxy类

static Object


newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。

  1. 实现InvocationHandler接口重写invoke方法

Object


invoke(Object proxy, Method method, Object[] args)

在代理实例上处理方法调用并返回结果。

  1. 代码案例
  1. MyInvocationHandler.java_代码示例

1 ?package com.heima.动态代理;

2

3 import java.lang.reflect.InvocationHandler;

4 import java.lang.reflect.Method;

5

6 public class MyInvocationHandler
implements InvocationHandler {

7         private Object target;

8

9         public MyInvocationHandler(Object target) {

10                 this.target = target;

11         }

12         @Override

13         public Object invoke(Object proxy, Method method, Object[] args)

14                         throws Throwable {

15                 System.out.println("权限校验");

16                 method.invoke(target, args);                                        //执行被代理target对象的方法

17                 System.out.println("日志记录");

18                 return null;

19         }

20

21 }

  1. Student.java_代码示例

    1 ?package com.heima.动态代理;

    2

    3 public interface Student {

    4         public
    void login();

    5

    6         public
    void submit();

    7 }

    1. StudentImp.java_代码示例

    1 ?package com.heima.动态代理;

    2

    3 public class StudentImp implements Student {

    4

    5         @Override

    6         public
    void login() {

    7                 System.out.println("登录");

    8         }

    9

    10         @Override

    11         public
    void submit() {

    12                 System.out.println("提交");

    13         }

    1. User.java_代码示例

    1 ?package com.heima.动态代理;

    2

    3 public interface User {

    4         public
    void add();

    5

    6         public
    void delete();

    1. }
    1. UserImp.java_代码示例

    1 ?package com.heima.动态代理;

    2

    3 public class UserImp implements User {

    4

    5         @Override

    6         public
    void add() {

    7                 //System.out.println("权限校验");

    8                 System.out.println("添加功能");

    9                 //System.out.println("日志记录");

    10         }

    11

    12         @Override

    13         public
    void delete() {

    14                 //System.out.println("权限校验");

    15                 System.out.println("删除功能");

    16                 //System.out.println("日志记录");

    17         }

    18

    1. Test.java_代码示例

    1 ?package com.heima.动态代理;

    2

    3 import java.lang.reflect.Proxy;

    4

    5 public class Test {

    6

    7         /**

    8          * @param args

    9          */

    10         public static
    void main(String[] args) {

    11                 /*UserImp ui = new UserImp();

    12                 ui.add();

    13                 ui.delete();

    14

    15                 System.out.println("-------------------------------");*/

    16                 /*

    17                  * public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,

    18                  * InvocationHandler h)

    19                  */

    20                 /*MyInvocationHandler m = new MyInvocationHandler(ui);

    21                 User u = (User)Proxy.newProxyInstance(ui.getClass().getClassLoader(), ui.getClass().getInterfaces(), m);

    22                 u.add();

    23                 u.delete();*/

    24

    25                 StudentImp si = new StudentImp();

    26                 si.login();

    27                 si.submit();

    28                 System.out.println("-------------------------------");

    29                 MyInvocationHandler m = new MyInvocationHandler(si);

    30                 Student s = (Student)Proxy.newProxyInstance(si.getClass().getClassLoader(), si.getClass().getInterfaces(), m);

    31

    32                 s.login();

    33                 s.submit();

    34         }

    35

    36 }

时间: 2024-11-12 13:25:26

反射,动态代理随笔的相关文章

Java语言中反射动态代理接口的解释与演示

Java语言中反射动态代理接口的解释与演示 Java在JDK1.3的时候引入了动态代理机制.可以运用在框架编程与平台编程时候捕获事件.审核数据.日志等功能实现,首先看一下设计模式的UML图解: 当你调用一个接口API时候,实际实现类继承该接口,调用时候经过proxy实现. 在Java中动态代理实现的两个关键接口类与class类分别如下: java.lang.reflect.Proxy java.lang.reflect.InvocationHandler 我们下面就通过InvocationHan

【Java核心技术】类型信息(Class对象 反射 动态代理)

1 Class对象 理解RTTI在Java中的工作原理,首先需要知道类型信息在运行时是如何表示的,这是由Class对象来完成的,它包含了与类有关的信息.Class对象就是用来创建所有"常规"对象的,Java使用Class对象来执行RTTI,即使你正在执行的是类似类型转换这样的操作. 每个类都会产生一个对应的Class对象,也就是保存在.class文件.所有类都是在对其第一次使用时,动态加载到JVM的,当程序创建一个对类的静态成员的引用时,就会加载这个类.Class对象仅在需要的时候才会

java 反射 动态代理

在上一篇文章中介绍Java注解的时候,多次提到了Java的反射API.与javax.lang.model不同的是,通过反射API可以获取程序在运行时刻的内部结构.反射API中提供的动态代理也是非常强大的功能,可以原生实现AOP中 的方法拦截功能.正如英文单词reflection的含义一样,使用反射API的时候就好像在看一个Java类在水中的倒影一样.知道了Java类的内部 结构之后,就可以与它进行交互,包括创建新的对象和调用对象中的方法等.这种交互方式与直接在源代码中使用的效果是相同的,但是又额

JAVA 反射 动态代理与AOP

摘自 b站尚硅谷JAVA视频教程 原文地址:https://www.cnblogs.com/superxuezhazha/p/12358469.html

JDK动态代理和CGLIB动态代理

转载自http://www.itzhai.com/java-dong-tai-dai-li-zhi-jdk-dong-tai-dai-li-he-cglib-dong-tai-dai-li-mian-xiang-qie-mian-bian-cheng-aop-yuan-li.html 静态代理 静态代理相对来说比较简单,无非就是聚合+多态: 参考:设计模式笔记 – Proxy 代理模式 (Design Pattern) 动态代理 我们知道,通过使用代理,可以在被代理的类的方法的前后添加一些处理方

日志 动态代理

日志log4j.properties 框架: log4j配置文件:log4j.rootLogger=TRACE,console,f1 log4j.appender.console=org.apache.log4j.ConsoleAppenderlog4j.appender.console.layout=org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern=[%p] %m [%t] %c [%l]

Java反射以及动态代理(上)

在常用的各种框架中,反射与动态代理很常见,也很重要.本篇就对这一小节的内容基础性地总结. 首先需要了解什么是类型信息,以及RTTI与反射的关系与区别. Java中,使用Class对象来表示所有类的对象.利用Class对象来获取类中的成员变量,构造函数以及方法,这些内容我们称之为类型信息.RTTI的含义是,在运行时识别一个对象的类型,但有一个前提,就是类型在编译时必须已知,这样才能用RTTI识别,并利用这些信息做一些有用的事情.但是如果在编译时,程序没有办法获知到这个对象所属的类,怎样才能使用这个

java反射与动态代理

Java反射与动态代理 Java反射机制可以动态地获取类的结构,动态地调用对象的方法,是java语言一个动态化的机制.java动态代理可以在不改变被调用对象源码的前提下,在被调用方法前后增加自己的操作,极大地降低了模块之间的耦合性.这些都是java的基础知识,要想成为一名合格的程序猿,必须掌握! Java反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为

Java反射—运用反射生成jdk动态代理

1.  核心类&接口 在Java的java.lang.reflect包下提供一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口可以生成jdk动态代理类或动态代理对象. Proxy是所有动态代理类的父类,它提供了两个静态方法来创建动态代理类和动态代理对象,如下: ?  static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) ?  static Objec