反射、类加载、静态代理,jdk动态代理,cglib代理

2024-05-29 04:44

本文主要是介绍反射、类加载、静态代理,jdk动态代理,cglib代理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

            一、 反射

          反射是在程序运行状态下,动态获取类的结构(属性,构造器,方法,注解),动态的创建类对象然后调用类中的属性方法。反射的起源Class,Class中包含类反射要使用的API

           获取Class的方法

public class Student{private Integer sId;private String sName;private Integer getsId() {return sId;}private void setsId(Integer sId) {this.sId = sId;}private String getsName() {return sName;}private void setsName(String sName) {this.sName = sName;}public Student(Integer sId, String sName) {this.sId = sId;this.sName = sName;}
}

反射的方法:

     0)  获取类类型 对象

               Class<Student> stu = Student.class  

     0.5)获取类 对象

                 Student      stuObj    =    stu.new Instance()  //默认获取无参构造方法

                 等价于

                Student     stuObj     =  stu.getConstructor().new Instance()

     1)获取属性

                  Field     sName =  stu.getDeclaredField(''sName'')

                                sName.setAccessible(true)

                  Field     sId  = stu.getDeclaredField("sId")

                                sId.setAccessible(true)

                属性设置值

                        sName.set(stuObj,''张三'')

                        sId.set(stuObj,1)

     2)获取方法

          Method  getsId   =    stu.getMethod("getsId")

          getsId.invoke(stuObj)

     3)   获取构造方法

          Constructor c   =      stu.getConstructor(Integer.class,String.class)

             Student s =  c.new Instance(1,"张三")

注意事项:

        反射获取方法,构造方法,属性方法中 方法名都有加Declared 与 不加Declared。

不加Declared:能够获取父子类中所有public修饰的方法

追加Declared:能够获取当前类中所有修饰符的方法

二)类加载

        方法区:放置读取的.class文件

        堆区:放置class文件生成的class对象

        

        类加载的过程:

        1)转载:查找并加载class文件

        2)链接:

                验证:验证字节码文件是否符合JVM规范。

                准备:为类的静态变量分配内存,初始化化默认值

                解析:类中的符号引用转换为直接引用

        3)初始化:为类的静态变量赋予正确的初始值

三)Proxy  代理模式

Spring 框架:

IOC控制反转:把项目javabean对象的创建以继生命周期交给spring框架管理

需要使用bean对象时,直接从Spring容器(bean对象的容器)中获取。

利用java的反射,实例化bean对象

AOP面向切面编程:两种动态代理实现

                jdk动态代理:实现接口

                cglib动态代理:单独的类,没有实现接口

在不修改源代码的情况下扩展功能

        静态代理:

                目标对象:执行类中方法

                代理对象:代理对象中包含目标对象,调用执行对象时可以额外添加功能

                注意:静态代理是提前写死的.class文件,并且两个对象类实现同一个接口。跟接口耦合性太高,改动麻烦。

        动态代理:

          jdk动态代理:

  实现InvocationHandler接口,重写invoke方法

    1)第一种方式: 直接调用invoke方法

          我们在其中内置一个Object对象用来实现对目标方法的调用

public class SqlsessionutilProxyJDK implements InvocationHandler {private Object obj; //代表目标对象@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String name = method.getName();if ("get".startsWith(name)||"select".startsWith(name)){Object invoke = method.invoke(obj, args);return invoke;}else {try {SqlSession session = SqlSessionUtil.getSession();Object invoke = method.invoke(obj, args);session.commit();return invoke;} catch (Exception e) {SqlSessionUtil.rollbackSession();throw new RuntimeException(e);}}}
}

   在Test类中

             

SqlsessionutilProxyJDK sqlsessionutilProxyJDK = new SqlsessionutilProxyJDK();
Object[] objects = {2,"在职"};
EmpService o =(EmpService) Proxy.newProxyInstance(new         EmpServiceImpl().getClass().getClassLoader(), new         EmpServiceImpl().getClass().getInterfaces(), new EmpServiceProxyJDK());
Method set = new EmpServiceImpl().getClass().getMethod("set", Integer.class, String.class);
sqlsessionutilProxyJDK.setObj(new EmpServiceImpl());
sqlsessionutilProxyJDK.invoke(o, set, objects);

2)简化方式:调用代理对象的相应方法

public class SqlsessionutilProxyJDK implements InvocationHandler {private Object obj;public void setObj(Object obj) {this.obj = obj;}public Object proxyInstance(Object obj){this.obj = obj;Object o = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);return o;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String name = method.getName();if ("get".startsWith(name)||"select".startsWith(name)){Object invoke = method.invoke(obj, args);return invoke;}else {try {SqlSession session = SqlSessionUtil.getSession();Object invoke = method.invoke(obj, args);session.commit();return invoke;} catch (Exception e) {SqlSessionUtil.rollbackSession();throw new RuntimeException(e);}}}
}

在Test类中:

         cglib代理:     

针对没有接口的类实现代理,实质上是创建这个类的子类,子类对象是代理对象,这个类对象是目标对象

需要在pom文件中引入第三方jar包  。如果在普通的java项目中,还需要有该jar包对应的依赖,但在Maven中会自动添加该jar包的依赖。

<!--        cglib--><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.12</version></dependency>
public class CGLIBProxy implements MethodInterceptor {public Object getProxyInstance(Object obj){Enhancer enhancer= new Enhancer();enhancer.setSuperclass(obj.getClass());enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("执行拓展功能");Object o1 = methodProxy.invokeSuper(o, objects);return o1;}
}

   在测试类中    

这篇关于反射、类加载、静态代理,jdk动态代理,cglib代理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1012683

相关文章

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

java中反射(Reflection)机制举例详解

《java中反射(Reflection)机制举例详解》Java中的反射机制是指Java程序在运行期间可以获取到一个对象的全部信息,:本文主要介绍java中反射(Reflection)机制的相关资料... 目录一、什么是反射?二、反射的用途三、获取Class对象四、Class类型的对象使用场景1五、Class

SpringBoot项目启动报错"找不到或无法加载主类"的解决方法

《SpringBoot项目启动报错找不到或无法加载主类的解决方法》在使用IntelliJIDEA开发基于SpringBoot框架的Java程序时,可能会出现找不到或无法加载主类com.example.... 目录一、问题描述二、排查过程三、解决方案一、问题描述在使用 IntelliJ IDEA 开发基于