“本文为传智大数据课程视频资料视频整理汇总”
1 反射
通过反射的方式可以获取class对象中的属性、方法、构造函数等
1 package thread.reflect; 2 3 import org.junit.Before; 4 import org.junit.Test; 5 6 import java.lang.reflect.Constructor; 7 import java.lang.reflect.Field; 8 import java.lang.reflect.Method; 9 10 public class MyReflect { 11 12 public String className = null; 13 @SuppressWarnings("rawtypes") 14 public Class personClass = null; 15 /** 16 * 反射Person类 17 * @throws Exception 18 */ 19 @Before 20 public void init() throws Exception { 21 className = "thread.reflect.Person"; 22 personClass = Class.forName(className); 23 } 24 /** 25 *获取某个class文件对象 26 */ 27 @Test 28 public void getClassName() throws Exception { 29 System.out.println(personClass); 30 } 31 /** 32 *获取某个class文件对象的另一种方式 33 */ 34 @Test 35 public void getClassName2() throws Exception { 36 System.out.println(Person.class); 37 } 38 /** 39 *创建一个class文件表示的实例对象,底层会调用空参数的构造方法 40 */ 41 @Test 42 public void getNewInstance() throws Exception { 43 System.out.println(personClass.newInstance()); 44 } 45 /** 46 *获取非私有的构造函数 47 */ 48 @SuppressWarnings({ "rawtypes", "unchecked" }) 49 @Test 50 public void getPublicConstructor() throws Exception { 51 Constructor constructor = personClass.getConstructor(Long.class,String.class); 52 Person person = (Person)constructor.newInstance(100L,"zhangsan"); 53 System.out.println(person.getId()); 54 System.out.println(person.getName()); 55 } 56 /** 57 *获得私有的构造函数 58 */ 59 @SuppressWarnings({ "rawtypes", "unchecked" }) 60 @Test 61 public void getPrivateConstructor() throws Exception { 62 Constructor con = personClass.getDeclaredConstructor(String.class); 63 con.setAccessible(true);//强制取消Java的权限检测 64 Person person2 = (Person)con.newInstance("zhangsan"); 65 System.out.println("**"+person2.getName()); 66 } 67 /** 68 *访问非私有的成员变量 69 */ 70 @SuppressWarnings({ "rawtypes", "unchecked" }) 71 @Test 72 public void getNotPrivateField() throws Exception { 73 Constructor constructor = personClass.getConstructor(Long.class,String.class); 74 Object obj = constructor.newInstance(100L,"zhangsan"); 75 76 Field field = personClass.getField("name"); 77 field.set(obj, "lisi"); 78 System.out.println(field.get(obj)); 79 } 80 /** 81 *访问私有的成员变量 82 */ 83 @SuppressWarnings({ "rawtypes", "unchecked" }) 84 @Test 85 public void getPrivateField() throws Exception { 86 Constructor constructor = personClass.getConstructor(Long.class); 87 Object obj = constructor.newInstance(100L); 88 89 Field field2 = personClass.getDeclaredField("id"); 90 field2.setAccessible(true);//强制取消Java的权限检测 91 field2.set(obj,10000L); 92 System.out.println(field2.get(obj)); 93 } 94 /** 95 *获取非私有的成员函数 96 */ 97 @SuppressWarnings({ "unchecked" }) 98 @Test 99 public void getNotPrivateMethod() throws Exception { 100 System.out.println(personClass.getMethod("toString")); 101 102 Object obj = personClass.newInstance();//获取空参的构造函数 103 Method toStringMethod = personClass.getMethod("toString"); 104 Object object = toStringMethod.invoke(obj); 105 System.out.println(object); 106 } 107 /** 108 *获取私有的成员函数 109 */ 110 @SuppressWarnings("unchecked") 111 @Test 112 public void getPrivateMethod() throws Exception { 113 Object obj = personClass.newInstance();//获取空参的构造函数 114 Method method = personClass.getDeclaredMethod("getSomeThing"); 115 method.setAccessible(true); 116 Object value = method.invoke(obj); 117 System.out.println(value); 118 119 } 120 /** 121 * 122 */ 123 @Test 124 public void otherMethod() throws Exception { 125 //当前加载这个class文件的那个类加载器对象 126 System.out.println(personClass.getClassLoader()); 127 //获取某个类实现的所有接口 128 Class[] interfaces = personClass.getInterfaces(); 129 for (Class class1 : interfaces) { 130 System.out.println(class1); 131 } 132 //反射当前这个类的直接父类 133 System.out.println(personClass.getGenericSuperclass()); 134 /** 135 * getResourceAsStream这个方法可以获取到一个输入流,这个输入流会关联到name所表示的那个文件上。 136 */ 137 //path 不以’/'开头时默认是从此类所在的包下取资源,以’/'开头则是从ClassPath根下获取。其只是通过path构造一个绝对路径,最终还是由ClassLoader获取资源。 138 System.out.println(personClass.getResourceAsStream("/log4j.properties")); 139 System.out.println(personClass.getResourceAsStream("log4j.properties")); 140 141 //判断当前的Class对象表示是否是数组 142 System.out.println(personClass.isArray()); 143 System.out.println(new String[3].getClass().isArray()); 144 145 //判断当前的Class对象表示是否是枚举类 146 System.out.println(personClass.isEnum()); 147 System.out.println(Class.forName("thread.reflect.City").isEnum()); 148 149 //判断当前的Class对象表示是否是接口 150 System.out.println(personClass.isInterface()); 151 System.out.println(Class.forName("thread.reflect.MyInterface").isInterface()); 152 153 154 } 155 156 }
使用反射进行socket调用
业务接口
1 package thread.reflect.socket; 2 3 public interface Business { 4 int getPrice(String goods); 5 }
业务实现
1 package thread.reflect.socket; 2 3 public class BusinessImpl implements Business { 4 @Override 5 public int getPrice(String good) { 6 return good.equals("clothes")?10:20; 7 } 8 }
服务端socket的处理类
1 package thread.reflect.socket; 2 3 import java.io.*; 4 import java.lang.reflect.Method; 5 import java.net.Socket; 6 7 public class ServerTask implements Runnable{ 8 private Socket socket; 9 public ServerTask(Socket socket){ 10 this.socket = socket; 11 } 12 13 @Override 14 public void run() { 15 InputStream in; 16 OutputStream out; 17 try { 18 in = socket.getInputStream(); 19 out = socket.getOutputStream(); 20 21 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 22 String request = br.readLine(); 23 String[] split = request.split(":"); 24 String className = split[0]; 25 String methodName = split[1]; 26 String methodParam= split[2]; 27 28 Class<?> forName = Class.forName(className); 29 System.out.println("calling class: " + forName); 30 Object newInstance = forName.newInstance(); 31 Method method = forName.getMethod(methodName,String.class); 32 System.out.println("calling method: " + method); 33 Object invoke = method.invoke(newInstance, methodParam); 34 int value = Integer.parseInt(invoke.toString()); 35 System.out.println("results: " + value); 36 37 38 PrintWriter pw = new PrintWriter(new BufferedOutputStream(out)); 39 pw.println(value); 40 pw.flush(); 41 42 br.close(); 43 pw.close(); 44 socket.close(); 45 46 } catch (Exception e) { 47 48 e.printStackTrace(); 49 } 50 51 } 52 53 }
服务端运行类
1 package thread.reflect.socket; 2 3 import java.net.InetSocketAddress; 4 import java.net.ServerSocket; 5 import java.net.Socket; 6 7 public class Server { 8 public static void main(String[] args) throws Exception { 9 ServerSocket server = new ServerSocket(); 10 server.bind(new InetSocketAddress("localhost",9898)); 11 while(true){ 12 Socket socket = server.accept(); 13 new Thread(new ServerTask(socket)).start(); 14 } 15 } 16 }
客户端运行类
1 package thread.reflect.socket; 2 3 import java.io.*; 4 import java.net.Socket; 5 6 public class Client { 7 public static void main(String[] args) throws Exception { 8 Socket socket = new Socket("localhost", 9898); 9 OutputStream out = socket.getOutputStream(); 10 InputStream in = socket.getInputStream(); 11 12 PrintWriter pw = new PrintWriter(new BufferedOutputStream(out)); 13 pw.println("thread.reflect.socket.BusinessImpl:getPrice:clothes"); 14 pw.flush(); 15 16 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 17 String readLine = br.readLine(); 18 19 System.out.println("client get result: " + readLine); 20 21 socket.close(); 22 23 24 25 } 26 }
2 动态代理
在之前的代码调用阶段,我们用action调用service的方法实现业务即可。
由于之前在service中实现的业务可能不能够满足当先客户的要求,需要我们重新修改service中的方法,但是service的方法不只在我们这个模块使用,在其他模块也在调用,其他模块调用的时候,现有的service方法已经能够满足业务需求,所以我们不能只为了我们的业务而修改service,导致其他模块授影响。
那怎么办呢?
可以通过动态代理的方式,扩展我们的service中的方法实现,使得在原有的方法中增加更多的业务,而不是实际修改service中的方法,这种实现技术就叫做动态代理。
动态代理:在不修改原业务的基础上,基于原业务方法,进行重新的扩展,实现新的业务。
例如下面的例子:
1、 旧业务
买家调用action,购买衣服,衣服在数据库的标价为50元,购买流程就是简单的调用。
2、 新业务
在原先的价格上可以使用优惠券,但是这个功能在以前没有实现过,我们通过代理类,代理了原先的接口方法,在这个方法的基础上,修改了返回值。
代理实现流程:
1、 书写代理类和代理方法,在代理方法中实现代理Proxy.newProxyInstance
2、 代理中需要的参数分别为:被代理的类的类加载器soneObjectclass.getClassLoader(),被代理类的所有实现接口new Class[] { Interface.class },句柄方法new InvocationHandler()
3、 在句柄方法中复写invoke方法,invoke方法的输入有3个参数Object proxy(代理类对象), Method method(被代理类的方法),Object[] args(被代理类方法的传入参数),在这个方法中,我们可以 定制化的开发新的业务。
4、 获取代理类,强转成被代理的接口
5、 最后,我们可以像没被代理一样,调用接口的认可方法,方法被调用后,方法名和参数列表将被传入代理类的invoke方法中,进行新业务的逻辑流程。
IBoss业务接口定义类
1 package thread.proxy.bossProxy; 2 3 public interface IBoss { 4 int sales(String size); 5 6 String giveBack(String size); 7 }
Boss业务接口实现类
1 package thread.proxy.bossProxy; 2 3 public class Boss implements IBoss{ 4 5 @Override 6 public int sales(String size) { 7 System.err.println("天猫小强旗舰店衣服A大小:"+size); 8 //这件衣服的价钱,从数据库读取 9 return 50; 10 } 11 12 @Override 13 public String giveBack(String size) { 14 return "退货退货"; 15 } 16 }
Boss业务调用类
1 package thread.proxy.bossProxy; 2 3 import org.junit.Test; 4 5 public class SalesAction { 6 /** 7 * 不使用代理,直接调用方法 8 * 方法中规定什么业务,就只能调用什么业务,规定什么返回值,就只能输出什么返回值 9 */ 10 @Test 11 public void saleByBossSelf() throws Exception { 12 IBoss boss = new Boss(); 13 System.out.println("老板自营!"); 14 int money = boss.sales("xxl");// 老板自己卖衣服,不需要客服,结果就是没有聊天记录 15 System.out.println("衣服成交价:" + money); 16 } 17 }
代理Boss业务实现类
1 package thread.proxy.bossProxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 7 public class ProxyBoss { 8 9 @SuppressWarnings("unchecked") 10 public static <T> T getProxy(final int discountCoupon,final Class<?> interfaceClass, final Class<?> implementsClass) 11 throws Exception { 12 return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), 13 new Class[] { interfaceClass }, new InvocationHandler() { 14 public Object invoke(Object proxy, Method method, 15 Object[] args) throws Throwable { 16 Integer returnValue = (Integer) method.invoke( 17 implementsClass.newInstance(), args);// 调用原始对象以后返回的值 18 return returnValue - discountCoupon; 19 } 20 }); 21 } 22 }
代理Boss业务调用类
1 package thread.proxy.bossProxy; 2 3 import org.junit.Test; 4 5 public class ProxySalesAction { 6 7 @Test 8 public void saleByProxy() throws Exception { 9 IBoss boss = ProxyBoss.getProxy(10,IBoss.class,Boss.class);// 将代理的方法实例化成接口 10 System.out.println("代理经营!"); 11 int money = boss.sales("xxl");// 调用接口的方法,实际上调用方式没有变 12 System.out.println("衣服成交价:" + money); 13 } 14 15 }