Java反射机制是一个很是强大的成果,在许多大型项目好比Spring, Mybatis中都可以瞥见反射的身影。通过反射机制我们可以在运行期间获取工具的范例信息,操作这一特性我们可以实现工场模式和署理模式等设计模式,同时也可以办理Java泛型擦除等令人苦恼的问题。本文我们就从实际应用的角度出发,软件开发,来应用一下Java的反射机制。
反射基本
p.s: 本文需要读者对反射机制的API有必然水平的相识,假如之前没有打仗过的话,发起先看一下官方文档的Quick Start。
在应用反射机制之前,首先我们先来看一下如何获取一个工具对应的反射类Class,在Java中我们有三种要领可以获取一个工具的反射类。
通过getClass要领
在Java中,每一个Object都有一个getClass()要领,通过getClass要领我们可以获取到这个工具对应的反射类:
String s = "http://www.ziwenxie.site"; Class<?> c = s.getClass();
通过forName要领
我们也可以挪用Class类的静态要领forName():
Class<?> c = Class.forName("java.lang.String");
利用.class
可能我们也可以直接利用.class:
Class<?> c = String.class;
获取范例信息
在文章开头我们就提到反射的一大长处就是可以答允我们在运行期间获取工具的范例信息,下面我们通过一个例子来详细看一下。
首先我们在typeinfo.interfacea包下面新建一个接口A:
package typeinfo.interfacea; public interface A { void f(); }
接着我们在typeinfo.packageaccess包下面新建一个类C,类C实现了接口A,而且我们还别的建设了几个用于测试的要领,留意下面几个要领的权限都是差异的。
package typeinfo.packageaccess; import typeinfo.interfacea.A; class C implements A { public void f() { System.out.println("public C.f()"); } public void g() { System.out.println("public C.g()"); } protected void v () { System.out.println("protected C.v()"); } void u() { System.out.println("package C.u()"); } private void w() { System.out.println("private C.w()"); } } public class HiddenC { public static A makeA() { return new C(); } }
在callHiddenMethod()要领中我们用到了几个新的API,个中getDeclaredMethod()按照要领名用于获取Class类指代工具本身声明的某个要领,然后我们通过挪用invoke()要领就可以触发工具的相关要领:
package typeinfo; import typeinfo.interfacea.A; import typeinfo.packageaccess.HiddenC; import java.lang.reflect.Method; public class HiddenImplementation { public static void main(String[] args) throws Exception { A a = HiddenC.makeA(); a.f(); System.out.println(a.getClass().getName()); // Oops! Reflection still allows us to call g(): callHiddenMethod(a, "g"); // And even methods that are less accessible! callHiddenMethod(a, "u"); callHiddenMethod(a, "v"); callHiddenMethod(a, "w"); } static void callHiddenMethod(Object a, String methodName) throws Exception { Method g = a.getClass().getDeclaredMethod(methodName); g.setAccessible(true); g.invoke(a); } }
从输出功效我们可以看出来,不管是public,default,protect照旧private要领,通过反射类我们都可以自由挪用。虽然这里我们只是为了显示反射的强大威力,软件开发,在实际开拓中这种能力照旧不倡导。
public C.f() typeinfo.packageaccess.C public C.g() package C.u() protected C.v() private C.w()
上面我们只是测试了Method工具,感乐趣的读者在熟悉了反射的API之后,不妨测试一下Filed,这里我们就不反复了。
操作动态署理实现面向切面编程
AOP是Spring提供的一个强大特性之一,AOP的意思是面向切面编程,就是说要疏散和业务不相关的代码,当我们需要新增相关的事务的时候,我们不想要对业务自己做修改。面向切面编程和面向工具酿成对比到底有什么长处呢,我们通过一个例子来看一下,对付新手来说,经常会写出下面这样的代码:
public class Example1 { public void execute() { // 记录日志 Logger logger = Logger.getLog(...); // 举办机能统计 PerformanceUtil.startTimer(...); // 权限查抄 if (!user.hasPrevilege()) { // 抛出异常 } // 执行真正的业务 executeTransaction(); PerformanceUtil.endTimer(); } }