1:所写的东西都经过验证,保证正确,环境jdk8,eclipse
2:在例子中,尽量以生产环境中实际代码为例,那种固定值什么的没什么意义
12312123434
DynamicQuartzJob Logger logger = LoggerFactory.getLogger(DynamicQuartzJob. executeInternal(JobExecutionContext jobexecutioncontext) JobDetailImpl jobDetail == JobExecutionException("can not find service info, because desription is empty"= name.split("\\." String beanName = serviceInfo[1 String methodName = serviceInfo[2== JobDataMap dataMap ==== JSONObject.toBean(JSONObject.fromObject(dataMap.get("data"
"%s %d" .aa = .bb = main(String[] args) String str = "{\r\n" + " \"aa\": \"zhangsan\",\r\n" + " \"bb\": 1\r\n" + "}" Test test = Test(); test = (Test) JSONObject.toBean(JSONObject.fromObject(str), Test.
5:拓展 (1):这张图片是常用的反射方法
(2 java.lang.reflect.* main(String[] args) HelloKitty ht = = Class clazz1 = HelloKitty. Class clazz2 = Class.forName("HelloKitty" ClassLoader c == String. Object obj = Constructor[] con =+ " " Method[] mm =+ " " Method m = clazz2.getMethod("walk",=+ " " Method m1 = clazz2.getMethod("walk", "hahahhha" Constructor cc = clazz2.getConstructor(.,String.= cc.newInstance(12,"blue" Field ffs = clazz2.getDeclaredField("age"29= String color = "pink" HelloKitty(.age = HelloKitty(.age =.color ="okokok" "hhhhhhhhhhhhh" talk(+ "----------" +
6:如果只是应用,网上文章一大堆,用就要知道一些具体的细节,不然 emmmm.....(不引战,懂就好)
这里说一下核心方法 method.invoke (1)这是invoke 的入口方法/** * Invokes the underlying method represented by this {@code Method} * object, on the specified object with the specified parameters. * Individual parameters are automatically unwrapped to match * primitive formal parameters, and both primitive and reference * parameters are subject to method invocation conversions as * necessary. * *If the underlying method is static, then the specified {@code obj} * argument is ignored. It may be null. * *If the number of formal parameters required by the underlying method is * 0, the supplied {@code args} array may be of length 0 or null. * *If the underlying method is an instance method, it is invoked * using dynamic method lookup as documented in The Java Language * Specification, Second Edition, section 15.12.4.4; in particular, * overriding based on the runtime type of the target object will occur. * *If the underlying method is static, the class that declared * the method is initialized if it has not already been initialized. * *If the method completes normally, the value it returns is * returned to the caller of invoke; if the value has a primitive * type, it is first appropriately wrapped in an object. However, * if the value has the type of an array of a primitive type, the * elements of the array are not wrapped in objects; in * other words, an array of primitive type is returned. If the * underlying method return type is void, the invocation returns * null. * * @param obj the object the underlying method is invoked from * @param args the arguments used for the method call * @return the result of dispatching the method represented by * this object on {@code obj} with parameters * {@code args} * * @exception IllegalAccessException if this {@code Method} object * is enforcing Java language access control and the underlying * method is inaccessible. * @exception IllegalArgumentException if the method is an * instance method and the specified object argument * is not an instance of the class or interface * declaring the underlying method (or of a subclass * or implementor thereof); if the number of actual * and formal parameters differ; if an unwrapping * conversion for primitive arguments fails; or if, * after possible unwrapping, a parameter value * cannot be converted to the corresponding formal * parameter type by a method invocation conversion. * @exception InvocationTargetException if the underlying method * throws an exception. * @exception NullPointerException if the specified object is null * and the method is an instance method. * @exception ExceptionInInitializerError if the initialization * provoked by this method fails. */@CallerSensitive public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class caller = Reflection.getCallerClass(); checkAccess(caller, clazz, obj, modifiers); } } MethodAccessor ma = methodAccessor; // read volatile if (ma == null) { ma = acquireMethodAccessor(); } return ma.invoke(obj, args); } (2)这段英文就不具体翻译啦,大致意思就是使用这个方法的各种可能情况,可能出现的问题,特别提醒,如果练习英语但是不会FQ,看不到国外的文章可以看底层代码的注释,一样可以练习英语 (3)开始正式解读这个方法,首先说一下这注解@CallerSensitive
2->反射1->
(3):invoke方法可以分为俩部分,一部分是访问控制检查,第一个if;第二部分就是MethodAccessor。invoke()实现执行方法
针对第一部分:简单来说就是访问权限检查,判断你是否可以访问这个方法
具体来说就是: 检查override,如果override为true,(Method的父类AccessibleObject中声明的变量)跳过检查;否则继续; 快速检查,判断该方法的修饰符modifiers是否为public,如果是跳过检查;否则继续; 详细检查,通过方法的(protected/private/package)修饰符或方法的声明类(例如子类可以访问父类的protected方法)与调用者caller之间的关系,判断caller是否有权限访问该方法。这里推荐看一下java四种访问权限,可能我们一般只用到private和public,但访问权限控制很重要,在一些多人合作的项目中尤为重要
这里就涉及到一个有意思的 Field(他父类也是AccessibleObject),他的override是false,导致我们在获取属性是常用setAccessible(true),当属性为private修饰
针对第二部分MethodAccessor.invoke();也就是真正的调用方法
这里有一个注释 // read volatile,这个很有意思是,volatile 是一个类型修饰符。volatile 的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略。//这是methodAccessor,对应的代码private volatile MethodAccessor methodAccessor;
MethodAccessor tmp = (root != ) tmp = (tmp != = tmp = reflectionFactory.newMethodAccessor( = (root != //这个方法可能会导致类膨胀 //类膨胀:类的膨胀(Bloating)指的是类中成员过多,甚至出现无序增加的情况。过大的类,会使得复杂度急剧增加,维护会变得更为困难。所以需要控制类的增长。 //,这篇文章讲解类膨胀= = =
注意这个方法acquireMethodAccessor,他有一个调用反射工厂的过程,ReflectionFactory利用MethodAccessor的字节码生成类MethodAccessorGenerator直接创建一个代理类,通过间接调用原方法完成invoke()任务; 这句话有几个概念:字节码,动态代理,反射最终都是调用原始类 这些遗留问题日后在解决把!!!
7:总结一下我理解的反射和应用场景
(1)反射的概念:可以理解成你去了一个小黑屋,里面可能有各种东西,都上了锁,你通过反射就能获取里面的东西,并且去除锁,知道东西的真正面目
(2)反射应用场景:简单来说就是“动态带有固定”,举个例子,比如我上面的例子,方法是动态的,但是方法的参数是固定的;传入的参数固定的,但是顺序未必和方法一致的;