当前位置: 首页 > news >正文

反射、类加载、静态代理,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;}
}

   在测试类中    

相关文章:

  • java8 stream流的用法
  • 命令模式(行为型)
  • spring分析工具_springboot startup analyze的部署和使用
  • 「vue同一个组件,不同路由切换时界面没有更新问题」
  • mysql - 为什么MySQL不建议使用NULL作为列默认值?
  • git仓库迁移
  • 【Linux】操作系统之冯诺依曼体系
  • 用HAL库改写江科大的stm32入门-6-3 PWM驱动LED呼吸灯
  • html中 table的 colspan和rowspan
  • 使用Golang调用腾讯云邮件模版发送邮件
  • SpringCloud学习笔记(一)
  • 日有所思的梦想
  • 探索python数据可视化的奥秘:打造专业绘图环境
  • 【全开源】JAVA情侣扭蛋机情侣游戏系统源码支持微信小程序+微信公众号+H5
  • Oracle中rman的增量备份使用分享
  • JAVA_NIO系列——Channel和Buffer详解
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • JS专题之继承
  • Just for fun——迅速写完快速排序
  • LeetCode算法系列_0891_子序列宽度之和
  • sessionStorage和localStorage
  • SpiderData 2019年2月13日 DApp数据排行榜
  • Zsh 开发指南(第十四篇 文件读写)
  • 阿里云应用高可用服务公测发布
  • 对超线程几个不同角度的解释
  • 官方解决所有 npm 全局安装权限问题
  • 记一次用 NodeJs 实现模拟登录的思路
  • 将 Measurements 和 Units 应用到物理学
  • 排序算法学习笔记
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 使用docker-compose进行多节点部署
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 物联网链路协议
  • 小程序01:wepy框架整合iview webapp UI
  • 协程
  • 携程小程序初体验
  • 自动记录MySQL慢查询快照脚本
  • 阿里云服务器购买完整流程
  • ​人工智能书单(数学基础篇)
  • #HarmonyOS:Web组件的使用
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • %check_box% in rails :coditions={:has_many , :through}
  • (1)(1.9) MSP (version 4.2)
  • (1)Android开发优化---------UI优化
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (C++20) consteval立即函数
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (done) 两个矩阵 “相似” 是什么意思?
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (php伪随机数生成)[GWCTF 2019]枯燥的抽奖
  • (二刷)代码随想录第15天|层序遍历 226.翻转二叉树 101.对称二叉树2
  • (分布式缓存)Redis持久化
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (六)什么是Vite——热更新时vite、webpack做了什么