当前位置:   article > 正文

Java大数据-反射和动态代理_大数据对象 反射

大数据对象 反射

反射的概念:

Java反射机制,是说在运行时刻,对于任何一个类,都能够知道它的所有属性和方法;对任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用方法的功能称为java的反射机制。 

假定给出以下Person类:

  1. package cn.itcast_04_reflect;
  2. import java.io.Serializable;
  3. public class Person implements Serializable,TestInterface{
  4. private Long id;
  5. public String name;
  6. public Person() {
  7. this.id = 100L;
  8. this.name = "afsdfasd";
  9. }
  10. public Person(Long id, String name) {
  11. // super();
  12. this.id = id;
  13. this.name = name;
  14. }
  15. public Person(Long id) {
  16. super();
  17. this.id = id;
  18. }
  19. @SuppressWarnings("unused")
  20. private Person(String name) {
  21. super();
  22. this.name = name+"=======";
  23. }
  24. public Long getId() {
  25. return id;
  26. }
  27. public void setId(Long id) {
  28. this.id = id;
  29. }
  30. public String getName() {
  31. return name;
  32. }
  33. public void setName(String name) {
  34. this.name = name;
  35. }
  36. public String toString() {
  37. return "Person [id=" + id + ", name=" + name + "]";
  38. }
  39. private String getSomeThing() {
  40. return "sdsadasdsasd";
  41. }
  42. private void testPrivate(){
  43. System.out.println("this is a private method");
  44. }
  45. }

给出该类的路径就能反射或者说剖析出该类所有信息,包括所有变量、方法、实现接口、父类等全部信息:

  1. package cn.itcast_04_reflect;
  2. import java.lang.reflect.Constructor;
  3. import java.lang.reflect.Field;
  4. import java.lang.reflect.Method;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. import org.junit.Before;
  8. import org.junit.Test;
  9. public class MyReflect {
  10. public String className = null;
  11. @SuppressWarnings("rawtypes")
  12. public Class personClass = null;
  13. /**
  14. * 反射Person类
  15. * @throws Exception
  16. */
  17. @Before
  18. public void init() throws Exception {
  19. className = "cn.itcast_04_reflect.Person";
  20. personClass = Class.forName(className);
  21. }
  22. /**
  23. *获取某个class文件对象
  24. */
  25. @Test
  26. public void getClassName() throws Exception {
  27. System.out.println(personClass);
  28. }
  29. /**
  30. *获取某个class文件对象的另一种方式
  31. */
  32. @Test
  33. public void getClassName2() throws Exception {
  34. System.out.println(Person.class);
  35. }
  36. /**
  37. *创建一个class文件表示的实例对象,底层会调用空参数的构造方法
  38. */
  39. @Test
  40. public void getNewInstance() throws Exception {
  41. System.out.println(personClass.newInstance());
  42. }
  43. /**
  44. *获取非私有的构造函数
  45. */
  46. @SuppressWarnings({ "rawtypes", "unchecked" })
  47. @Test
  48. public void getPublicConstructor() throws Exception {
  49. Constructor constructor = personClass.getConstructor(Long.class,String.class);
  50. Person person = (Person)constructor.newInstance(100L,"zhangsan");
  51. System.out.println(person.getId());
  52. System.out.println(person.getName());
  53. }
  54. /**
  55. *获得私有的构造函数
  56. */
  57. @SuppressWarnings({ "rawtypes", "unchecked" })
  58. @Test
  59. public void getPrivateConstructor() throws Exception {
  60. Constructor con = personClass.getDeclaredConstructor(String.class);
  61. con.setAccessible(true);//强制取消Java的权限检测
  62. Person person2 = (Person)con.newInstance("zhangsan");
  63. System.out.println("**"+person2.getName());
  64. }
  65. /**
  66. *访问非私有的成员变量
  67. */
  68. @SuppressWarnings({ "rawtypes", "unchecked" })
  69. @Test
  70. public void getNotPrivateField() throws Exception {
  71. Constructor constructor = personClass.getConstructor(Long.class,String.class);
  72. Object obj = constructor.newInstance(100L,"zhangsan");
  73. Field field = personClass.getField("name");
  74. field.set(obj, "lisi");
  75. System.out.println(field.get(obj));
  76. }
  77. /**
  78. *访问私有的成员变量
  79. */
  80. @SuppressWarnings({ "rawtypes", "unchecked" })
  81. @Test
  82. public void getPrivateField() throws Exception {
  83. Constructor constructor = personClass.getConstructor(Long.class);
  84. Object obj = constructor.newInstance(100L);
  85. Field field2 = personClass.getDeclaredField("id");
  86. field2.setAccessible(true);//强制取消Java的权限检测
  87. field2.set(obj,10000L);
  88. System.out.println(field2.get(obj));
  89. }
  90. /**
  91. *获取非私有的成员函数
  92. */
  93. @SuppressWarnings({ "unchecked" })
  94. @Test
  95. public void getNotPrivateMethod() throws Exception {
  96. System.out.println(personClass.getMethod("toString"));
  97. Object obj = personClass.newInstance();//获取空参的构造函数
  98. Method toStringMethod = personClass.getMethod("toString");
  99. Object object = toStringMethod.invoke(obj);
  100. System.out.println(object);
  101. }
  102. /**
  103. *获取私有的成员函数
  104. */
  105. @SuppressWarnings("unchecked")
  106. @Test
  107. public void getPrivateMethod() throws Exception {
  108. Object obj = personClass.newInstance();//获取空参的构造函数
  109. Method method = personClass.getDeclaredMethod("getSomeThing");
  110. method.setAccessible(true);
  111. Object value = method.invoke(obj);
  112. System.out.println(value);
  113. }
  114. /**
  115. *
  116. */
  117. @Test
  118. public void otherMethod() throws Exception {
  119. //当前加载这个class文件的那个类加载器对象
  120. System.out.println(personClass.getClassLoader());
  121. //获取某个类实现的所有接口
  122. Class[] interfaces = personClass.getInterfaces();
  123. for (Class class1 : interfaces) {
  124. System.out.println(class1);
  125. }
  126. //反射当前这个类的直接父类
  127. System.out.println(personClass.getGenericSuperclass());
  128. /**
  129. * getResourceAsStream这个方法可以获取到一个输入流,这个输入流会关联到name所表示的那个文件上。
  130. */
  131. //path 不以’/'开头时默认是从此类所在的包下取资源,以’/'开头则是从ClassPath根下获取。其只是通过path构造一个绝对路径,最终还是由ClassLoader获取资源。
  132. System.out.println(personClass.getResourceAsStream("/log4j.properties"));
  133. System.out.println(personClass.getResourceAsStream("log4j.properties"));
  134. //判断当前的Class对象表示是否是数组
  135. System.out.println(personClass.isArray());
  136. System.out.println(new String[3].getClass().isArray());
  137. //判断当前的Class对象表示是否是枚举类
  138. System.out.println(personClass.isEnum());
  139. System.out.println(Class.forName("cn.itcast_04_reflect.City").isEnum());
  140. //判断当前的Class对象表示是否是接口
  141. System.out.println(personClass.isInterface());
  142. System.out.println(Class.forName("cn.itcast_04_reflect.TestInterface").isInterface());
  143. }
  144. }

动态代理:

        假设我们当前类service中方法实现的业务可能不能够满足当先客户的要求,需要我们重新修改service中的方法,但是service的方法不只在我们这个模块使用,在其他模块也在调用,其他模块调用的时候,现有的service方法已经能够满足业务需求,所以我们不能只为了我们的业务而修改service,导致其他模块授影响。

       那怎么办呢?

       可以通过动态代理的方式,扩展我们的service中的方法实现,使得在原有的方法中增加更多的业务,而不是实际修改service中的方法,这种实现技术就叫做动态代理。

       动态代理:在不修改原业务的基础上,基于原业务方法,进行重新的扩展,实现新的业务。

       例如下面的例子:

  1. 旧业务

买家调用action,购买衣服,衣服在数据库的标价为50元,购买流程就是简单的调用。

  1. 新业务

在原先的价格上可以使用优惠券,但是这个功能在以前没有实现过,我们通过代理类,代理了原先的接口方法,在这个方法的基础上,修改了返回值。

旧业务定义了一个接口和该接口的实现类,以及旧业务的测试实现:

  1. package cn.itcast_05_proxy.service;
  2. /**
  3. * 这是一个业务的接口,这个接口中的业务就是返回衣服的价格
  4. *
  5. */
  6. public interface IBoss {//接口
  7. int yifu(String size);
  8. }
  9. package cn.itcast_05_proxy.service.impl;
  10. import cn.itcast_05_proxy.service.IBoss;
  11. /**
  12. * 实现了卖衣服的接口
  13. */
  14. public class Boss implements IBoss{
  15. public int yifu(String size){
  16. System.err.println("天猫小强旗舰店,老板给客户发快递----衣服型号:"+size);
  17. //这件衣服的价钱,从数据库读取
  18. return 50;
  19. }
  20. }
  21. package cn.itcast_05_proxy.action;
  22. import org.junit.Test;
  23. import cn.itcast_05_proxy.service.IBoss;
  24. import cn.itcast_05_proxy.service.impl.Boss;
  25. public class SaleAction {
  26. /**
  27. * 旧业务的实现效果
  28. * 不使用代理,直接调用方法
  29. * 方法中规定什么业务,就只能调用什么业务,规定什么返回值,就只能输出什么返回值
  30. */
  31. @Test
  32. public void saleByBossSelf() throws Exception {
  33. IBoss boss = new Boss();
  34. System.out.println("老板自营!");
  35. int money = boss.yifu("xxl");// 老板自己卖衣服,不需要客服,结果就是没有聊天记录
  36. System.out.println("衣服成交价:" + money);
  37. }
  38. }

新业务增加促销优惠券功能,但是因为可能其他模块还需要原有功能,不能改动旧业务代码。

动态代理:先写个代理的工具类,对接口方法进行代理,将旧业务+新增功能后的逻辑封装。

  1. public class ProxyBoss {
  2. /**
  3. * 对接口方法进行代理
  4. */
  5. @SuppressWarnings("unchecked")
  6. public static <T> T getProxy(final int discountCoupon,
  7. final Class<?> interfaceClass, final Class<?> implementsClass)
  8. throws Exception {
  9. return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),
  10. new Class[] { interfaceClass }, new InvocationHandler() {
  11. public Object invoke(Object proxy, Method method,
  12. Object[] args) throws Throwable {
  13. Integer returnValue = (Integer) method.invoke(
  14. implementsClass.newInstance(), args);// 调用原始对象以后返回的值
  15. return returnValue - discountCoupon;
  16. }
  17. });
  18. }
  19. }

新业务的测试实现:

  1. import org.junit.Test;
  2. import cn.itcast_05_proxy.proxyclass.ProxyBoss;
  3. import cn.itcast_05_proxy.service.IBoss;
  4. import cn.itcast_05_proxy.service.impl.Boss;
  5. /**
  6. * 什么是动态代理? 简单的写一个模板接口,剩下的个性化工作,好给动态代理来完成!
  7. */
  8. public class ProxySaleAction {
  9. /**
  10. *使用代理,在这个代理中,只代理了Boss的yifu方法
  11. *定制化业务,可以改变原接口的参数、返回值等
  12. */
  13. @Test
  14. public void saleByProxy() throws Exception {
  15. IBoss boss = ProxyBoss.getProxy(10,IBoss.class,Boss.class);// 将代理的方法实例化成接口
  16. //IBoss boss = new Boss();// 将代理的方法实例化成接口
  17. System.out.println("代理经营!");
  18. int money = boss.yifu("xxl");// 调用接口的方法,实际上调用方式没有变
  19. System.out.println("衣服成交价:" + money);
  20. }
  21. }

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/199412
推荐阅读
相关标签
  

闽ICP备14008679号