1、反射是什么
反射是jvm运行期间,动态的获取class模板的信息(属性、方法等)
2、java提供了Class、AccessibleObject 、Array 、Constructor 、Field 、Method 、Modifier 、Proxy
类来操作反射信息
2.1 Class 类
Class类提供了反射需要的大部分信息,比如
Class c = Class.forName("main.test.Relf"); //获取模板类 Field field = c.getField("message"); //读取类属性
2.2 AccessibleObject 类
AccessibleObject提供了设置访问权限(一般要获取私有属性的动态信息,需要设置权限为允许,这是面向对象的封装特性)
RelfEntity relf = new RelfEntity(); Field field = relf.getClass().getDeclaredField("message"); AccessibleObject.setAccessible(new AccessibleObject[]{field},true); //设置访问私有权限 field.set(relf,"hello"); System.out.println(field.get(relf));
2.3 Array类
这个类主要是提供获取反射数组元素信息,比如
RelfEntity relf = new RelfEntity(); Field [] field = relf.getClass().getDeclaredFields(); AccessibleObject.setAccessible(field,true); Field field1 = (Field) Array.get(field,0); //获取下标为0的属性 field1.set(relf,"hello"); System.out.println(field1.get(relf));
2.4 Constructor、Field 类
Constructor类基本很少用,里面有可以动态获取参数、参数类型、创建对象等
Field 类用来获取属性信息
2.5 Method 类
Method这个用的比较多,为什么单独说这个方法,是因为我们的动态代理其实也是这个方法中实现的
RelfEntity relf = new RelfEntity(); Method method = relf.getClass().getDeclaredMethod("setMessage",String.class); method.invoke(relf,"test..."); //动态调用 System.out.println(relf.getMessage());
2.6 Modifier 类
这个类主要是来查看访问类型的,比如我们要查看属性的类型
RelfEntity relf = new RelfEntity(); Field field = relf.getClass().getDeclaredField("message"); int modifier = field.getModifiers(); if(Modifier.isPrivate(modifier)){ System.out.println("is private"); }
2.7 proxy
proxy类是我们实现动态代理的类,首先说下动态代理的思想是解耦,在spring aop就是通过动态代理的方式实现,它可以使得业务逻辑和非业务逻辑分开,比如(我们可以在业务前后加上非业务逻辑处理)
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { main.test.entity.Proxy proxy = getproxy(new ProxyBook()); proxy.buySome("java"); } public static main.test.entity.Proxy getproxy(main.test.entity.Proxy proxyReal){ Relf relf = new Relf(proxyReal); main.test.entity.Proxy proxy = (main.test.entity.Proxy) Proxy.newProxyInstance(main.test.entity.Proxy.class.getClassLoader(),new Class[]{main.test.entity.Proxy.class},relf); return proxy; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("询问是否有货..."); //非业务逻辑之前处理 method.invoke(entrust,args); System.out.println("购买完成..."); //非业务逻辑之后处理 return null; }
以上只是简单了介绍了反射的使用,一般需要程序解耦除了需要良好的设计能力还需要语言本身的解耦能力。