注解
1.自定义注解
1.1注解的基础
-
注解的定义:JAVA文件叫做Annotation,用**@interface**表示
-
元注解: @interface上面按照需要注解上一些东西,包括**@Retention、@Target、@Document、@Inherited**四种
-
注解的保留策略:
- @Retention(RetentionPolicy.SOURCE) //注解仅存在源码中,在class字节码中不包含
- @Retention(RetentionPolicy.CLASS) //默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
- @Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时通过反射获取到
-
注解的作用目标
注解 说明 @Target(ElementType.TYPE) 接口、类、枚举、注解 @Target(ElementType.FIELD) 字段、枚举的常量 @Target(ElementType.METHOD) 方法 @Target(ElementType.PARAMETER) 方法参数 @Target(ElementType.CONSTRUCTOR) 构造函数 @Target(ElementType.LOCAL_VARIABLE) 局部变量 @Target(ElementType.ANNOTATION_TYPE) 注解 @Target(ElementType.PACKAGE) 包 -
注解包含在javadoc中**@Documented**
-
注解可以被继承**@Inherited**
-
注解解析器: 用来解析自定义注解
1.2通过注解进行赋值(结合工厂模式)
1.2.1自定义注解
@Documented
@Inherited
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Init {
public String value() default "";
}
1.2.2在数据模型使用注解
public class User {
private String name;
private String age;
public String getName() {
return name;
}
@Init(value = "liang")
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
@Init(value = "23")
public void setAge(String age) {
this.age = age;
}
}
1.2.3用"构造工厂"充当"注解解析器"
public class UserFactory {
public static User create(){
User user = new User();
Method[] declaredMethods = User.class.getDeclaredMethods();
try {
for (Method method:declaredMethods){
if (method.isAnnotationPresent(Init.class)){
Init annotation = method.getAnnotation(Init.class);
method.invoke(user,annotation.value());
}
}
}catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
return null;
}
return user;
}
}
-
结合源码看
@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); }
1.2.4运行的代码
public class test {
public static void main(String[] args) {
User user = UserFactory.create();
System.out.println(user.getAge());
System.out.println(user.getAge());
}
}
1.3通过注解进行校验
1.3.1自定义注解
@Documented
@Inherited
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Validate {
public int min() default 1;
public int max() default 10;
public boolean isNotNull() default true;
}
1.3.2在数据模型使用注解
public class User {
@Validate(min = 2,max = 5)
private String name;
@Validate(isNotNull = false)
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
1.3.3注解解析器
public class UserCheck {
public static boolean check(User user){
if (user == null){
System.out.println("校验对象为空");
return false;
}
Field[] declaredFields = User.class.getDeclaredFields();
for (Field field:declaredFields){
//注解Validate是否在field上面
if (field.isAnnotationPresent(Validate.class)){
Validate annotation = field.getAnnotation(Validate.class);
if (field.getName().equals("age")){
if (user.getAge() == null){
if (annotation.isNotNull()){
System.out.println("年龄可空检验不通过;不可为空");
return false;
}else{
System.out.println("年龄可检验通过,可以为空");
continue;
}
}else{
System.out.println("年龄可校验通过");
}
if (user.getAge().length() < annotation.min()){
System.out.println("年龄最小长度校验不通过");
return false;
}else {
System.out.println("年龄最小长度校验通过");
}
if (user.getAge().length() > annotation.max()){
System.out.println("年龄最长度校验不通过");
return false;
}else{
System.out.println("年龄最长度校验通过");
}
}
if (field.getName().equals("name")){
if (user.getName() == null){
if (annotation.isNotNull()){
System.out.println("名字校验不通过:不可为空");
return false;
}else {
System.out.println("名字可检验通过:可以为空");
continue;
}
}else {
System.out.println("名字可空校验通过");
}
if (user.getName().length() < annotation.min()){
System.out.println("名字最小长度校验不通过");
return false;
}else{
System.out.println("名字最小长度校验通过");
}
if (user.getName().length() > annotation.max()){
System.out.println("名字最长度校验不通过");
return false;
}else{
System.out.println("名字最长度校验通过");
}
}
}
}
return true;
}
}
1.3.4运行的代码
public class Test {
public static void main(String[] args) {
User user = new User();
user.setName("liang");
user.setAge("234");
System.out.println(UserCheck.check(user));
}
}
1.4invoke方法
1.4.1invoke方法用来运行时动态地调用某个实例的方法
###########################源码###################
@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);
}
1.4.2权限检查
-
invoke方法会首先检查AccessibleObject的override属性值,AccessibleObject类是Field、Method和Constructor对象的基类,它提供了将反射的对象标记为使用时取消默认java语言访问控制检查的能力
-
override的默认是false,表示需要权限调用规则,调用方法时需要检查权限,我们也可以用setAccessible方法设置为true,若override的值为true,表示忽略权限规则,调用方法时无需检查权限(也就是说可以调用任意的private方法,违反了封装的意义)
-
如果override属性默认值false,则进行进一步的权限检查
-
首先用**Reflection.quickCheckMemberAccess(clazz,modifiers)方法检查方法是否为public,如果是的话跳出本步,如果不是public方法,那么用Reflection.getCallerClass()**方法获取调用这个方法的Class对象,这是一个native方法:
@CallerSensitive public static native Class<?> getCallerClass();
-
在OpenJDK的源码中找到此方法的JNI入口(Reflection.c)
JNIEXPORT jclass JNICALL Java_sun_reflect_Reflection_getCallerClass__ (JNIEnv *env, jclass unused) { return JVM_GetCallerClass(env, JVM_CALLER_DEPTH); }
-
其中JVM_GetCallerClass的源码如下(JVM.cpp)
JVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env, int depth)) JVMWrapper("JVM_GetCallerClass"); // Pre-JDK 8 and early builds of JDK 8 don't have a CallerSensitive annotation; or // sun.reflect.Reflection.getCallerClass with a depth parameter is provided // temporarily for existing code to use until a replacement API is defined. if (SystemDictionary::reflect_CallerSensitive_klass() == NULL || depth != JVM_CALLER_DEPTH) { Klass* k = thread->security_get_caller_class(depth); return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror()); } // Getting the class of the caller frame. // // The call stack at this point looks something like this: // // [0] [ @CallerSensitive public sun.reflect.Reflection.getCallerClass ] // [1] [ @CallerSensitive API.method ] // [.] [ (skipped intermediate frames) ] // [n] [ caller ] vframeStream vfst(thread); // Cf. LibraryCallKit::inline_native_Reflection_getCallerClass for (int n = 0; !vfst.at_end(); vfst.security_next(), n++) { Method* m = vfst.method(); assert(m != NULL, "sanity"); switch (n) { case 0: // This must only be called from Reflection.getCallerClass if (m->intrinsic_id() != vmIntrinsics::_getCallerClass) { THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVM_GetCallerClass must only be called from Reflection.getCallerClass"); } // fall-through case 1: // Frame 0 and 1 must be caller sensitive. if (!m->caller_sensitive()) { THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), err_msg("CallerSensitive annotation expected at frame %d", n)); } break; default: if (!m->is_ignored_by_security_stack_walk()) { // We have reached the desired frame; return the holder class. return (jclass) JNIHandles::make_local(env, m->method_holder()->java_mirror()); } break; } } return NULL; JVM_END
-
获取了这个Class对象caller后用checkAccess方法做一次快速的权限校验,其实现为:
volatile Object securityCheckCache; void checkAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers) throws IllegalAccessException { if (caller == clazz) { // 快速校验 return; // 权限通过校验 } Object cache = securityCheckCache; // read volatile Class<?> targetClass = clazz; if (obj != null && Modifier.isProtected(modifiers) && ((targetClass = obj.getClass()) != clazz)) { // Must match a 2-list of { caller, targetClass }. if (cache instanceof Class[]) { Class<?>[] cache2 = (Class<?>[]) cache; if (cache2[1] == targetClass && cache2[0] == caller) { return; // ACCESS IS OK } // (Test cache[1] first since range check for [1] // subsumes range check for [0].) } } else if (cache == caller) { // Non-protected case (or obj.class == this.clazz). return; // ACCESS IS OK } // If no return, fall through to the slow path. slowCheckMemberAccess(caller, clazz, obj, modifiers, targetClass); }
-
首先先执行一次快速校验,一旦调用方法的Class正确则权限检查通过
-
若未通过,则创建一个缓存,中间再进行一堆检查(比如检验是否为protected属性)
-
如果上面的所有权限检查都未通过,那么将执行更加详细的检查,其实现为:
// Keep all this slow stuff out of line: void slowCheckMemberAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers, Class<?> targetClass) throws IllegalAccessException { Reflection.ensureMemberAccess(caller, clazz, obj, modifiers); // Success: Update the cache. Object cache = ((targetClass == clazz) ? caller : new Class<?>[] { caller, targetClass }); // Note: The two cache elements are not volatile, // but they are effectively final. The Java memory model // guarantees that the initializing stores for the cache // elements will occur before the volatile write. securityCheckCache = cache; // write volatile }
-
大体意思就是,用Reflection.ensureMemberAccess方法继续检查权限,若检查通过就更新缓存,这样下一次同一个类调用同一个方法时就不用执行权限检查了,这就是一种简单的缓存机制,由于JMM的到这里,前期的权限检查工作就结束,如果没有通过检查则会抛出异常,如果通过检查则到下一步。
-
-
1.4.3调用MethodAccessor的invoke方法
- Method.invoke()实际上并不是自己实现的反射调用逻辑,而是委托给sun.reflect.MethodAccessor来处理
- 首先要了解Method对象的基本构成,每个java方法有且只有一个Method对象作为root,它相当于根对象,对用户不可见。当我们创建Method对象时,代码中获得的Method对象都相当于它的副本(或引用)。root对象持有一个MethodAccessor对象,所有所有获取到Method对象都共享这个MethodAccessor对象,因此必须保证它再内存中的可见性,root对象其声明及注释为:
private volatile MethodAccessor methodAccessor;
// For sharing of MethodAccessors. This branching structure is
// currently only two levels deep (i.e., one root Method and
// potentially many Method objects pointing to it.)
//
// If this branching structure would ever contain cycles, deadlocks can
// occur in annotation code.
private Method root;
-
那么MethodAccessor到底是什么
/** This interface provides the declaration for java.lang.reflect.Method.invoke(). Each Method object is configured with a (possibly dynamically-generated) class which implements this interface. */ public interface MethodAccessor { /** Matches specification in {@link java.lang.reflect.Method} */ public Object invoke(Object obj, Object[] args) throws IllegalArgumentException, InvocationTargetException; }
-
可以看到MethodAccessor是一个接口,定义了invoke方法,分析其Usage可得它的具体实现类有
sun.reflect.DelegatingMethodAccessorImpl sun.reflect.MethodAccessorImpl sun.reflect.NativeMethodAccessorImpl
【重大遗留问题】 我理解不了:https://www.sczyh30.com/posts/Java/java-reflection-2/
1.5总结
public class Reflecttion {
public static void main(String[] args) {
/**
* 获取Class对象 三种方式
* Class.forName("")
* 类名.class
* 对象名.getClass()
*
*/
Class clazz = Student.class;
/* Class clazz1 = null;
try {
clazz1 = Class.forName("com.lc.testReflection.Student");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Class clazz2 = (new Student()).getClass();*/
/**
* Class用来描述目标类的结构
* getInterfaces() //返回运行时实现的全部接口
* getSuperclass() //返回运行时类的父类
* getConstructors() //返回运行时类的public构造方法
* getDeclaredConstructors() //返回运行时类的全部构造方法
* getMethods() //返回运行时类的public方法,包括其继承的公用方法
* getDeclaredMethods() //返回运行时类的全部方法,但是不包括继承的方法
* getFields() //返回运行时类的public成员变量,包括继承的public成员变量
* getDeclaredFields() //返回运行时类的全部成员变量,但不包括继承的成员变量
* getMethod(String name,Class<?> ... parameterTypes) //返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应的Class的对象
*/
//返回运行时类实现的全部接口
Class[] interfaces = clazz.getInterfaces();
for (Class anInterface : interfaces) {
System.out.println(anInterface);
}
//返回运行时类的父类
Class superclass = clazz.getSuperclass();
System.out.println(superclass);
//返回运行时类的public构造方法
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//返回运行时类的全部构造方法
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
//返回运行时类的public方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//返回运行时类的全部方法
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
//返回运行时类的public成员变量
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
//返回运行类的全部成员变量
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应的Class的对象
Method method = clazz.getMethod("方法名称",参数类型.class,...)
/**
* getReturnType(); //返回方法的返回值类型
* getParameterTypes(); //返回方法的参数列表
* getModifiers(); //返回方法的访问权限修饰符 0:无修饰 1:public 2:private 4:protected
* getName(); //返回方法名
* getExceptionTypes(); //返回方法的异常信息
*
*
* 获取方法后可以通过invoke();//来完成方法的调取
*/
//获取指定方法的(how())
Method how = null;
try {
how = clazz.getDeclaredMethod("how", null);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//返回方法的返回值类型
Class<?> returnType = how.getReturnType();
System.out.println(returnType);
//返回方法的参数列表
Class<?>[] parameterTypes = how.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println(parameterType);
}
//返回方法的访问权限修饰符
int modifiers = how.getModifiers();
System.out.println(modifiers);
//返回方法名
String name = how.getName();
System.out.println(name);
//返回方法的异常信息
Class<?>[] exceptionTypes = how.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
/**
* Field用来描述运行时类的成员变量
* getModifiers(); //返回成员变量访问权限修饰符
* getType(); //返回成员变量的数据类型
* getName(); //返回成员变量的名称
*
* 获取成员变量后
* ##setAccessible(boolean);//值为ture,表示能修改,值为false,表示不能修改,会抛出异常,默认为false(任意修饰符)
* set(Object object,Types types);//eg:field.set(student,1)
*
*/
//指定成员变量
Field name1 = null;
try {
name1 = clazz.getField("name");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
//返回成员变量的访问权限修饰符
int modifiers1 = name1.getModifiers();
System.out.println(modifiers1);
//返回成员变量的数据类型
Class<?> type = name1.getType();
System.out.println(type);
//返回成员变量的名称
String name2 = name1.getName();
System.out.println(name2);
/**
* constructor用来描述运行时类的构造方法
* getModifiers(); //返回构造方法的访问权限修饰符
* getName(); //返回构造方法名称
* getParameterTypes(); //返回构造方法参数列表
*
* 通过指定参数列表获取对应构造函数
* eg:clazz.getConstructor(int.class,String.class)
*/
Constructor constructor = null;
try {
constructor = clazz.getConstructor(null);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//返回构造方法的访问权限修饰符
int modifiers2 = constructor.getModifiers();
System.out.println(modifiers2);
//返回构造方法名称
String name3 = constructor.getName();
System.out.println(name3);
//返回构造方法参数列表
Class[] parameterTypes1 = constructor.getParameterTypes();
for (Class aClass : parameterTypes1) {
System.out.println(aClass);
}
}
}
class Student{
private int id;
public String name;
public Student() {
}
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private void show(){
System.out.println("id"+id+","+"name"+name);
}
protected String how(){
int a = 10;
int b = 12;
return Integer.toString(a+b);
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
//动态代理
class MyInvocationHandler implements InvocationHandler{
private Object object = null;
public Object bind(Object object){
this.object = object;
return Proxy.newProxyInstance(MyInvocationHandler.class.getClassLoader(),object.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(object,args);
return result;
}
}
}