反射:

**定义:**在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能调用它的属性和方法(private也可以),这种动态获取信息以及动态调用的功能叫反射。

用途:如果一个类定义了私有化,可以通过反射机制来获取

与反射相关的类:

Class类,Field类(属性),Method类(方法),Constructor类(构造器)

Class类(ReflectTarget)

  • 用最多的,最方便的就是Class.forName(String className);--根据类名返回类的对象
    Class clasz = Class.forName("demo.pattern.reflect.ReflectTarget");
    
  • 获取类的实例
    (ReflectTarget)clasz.getConstructor().newInstance();
    

Constructor

1.批量获取构造方法:

 public Constructor[] getConstructors():所有"公有的"构造方法public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)

2.获取单个方法:

public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

Filed

1.批量获取属性

Field[] getFields():获取所有的"公有字段" 包含继承字段
Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有; 不包含继承的字段

2.获取单个的

public Field getField(String fieldName):获取某个"公有的"字段; 包含继承字段
public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的) 不包含继承的字段

3.设置值

*   设置字段的值:
*      Field --> public void set(Object obj,Object value):
*                  参数说明:
*                  1.obj:要设置的字段所在的对象;
*                  2.value:要为字段设置的值;
*

Method

1.批量的

public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)

2.单个的

public Method getMethod(String name,Class<?>... parameterTypes):
*                  参数:
*                      name : 方法名;
*                      Class ... : 形参的Class类型对象
public Method getDeclaredMethod(String name,Class<?>... parameterTypes)

3.调用

*   调用方法:
*      Method --> public Object invoke(Object obj,Object... args):
*                  参数说明:
*                  obj : 要调用方法的对象;
*                  args:调用方式时所传递的实参;

案例:

1.获取类Class相关的方法
package demo.pattern.reflect;
import lombok.SneakyThrows;
public class ReflectTarget {@SneakyThrowspublic static void main(String[] args) {// 通过反射的方法获取类ReflectTarget reflectTarget = new ReflectTarget();Class aClass1 = reflectTarget.getClass();System.out.println("1st : " + aClass1.getName());//2Class aClass2 = ReflectTarget.class;System.out.println("2st : " + aClass2.getName());//判断是否相等System.out.println(aClass1==aClass2);//3.Class aClass3 = Class.forName("demo.pattern.reflect.ReflectTarget");System.out.println("3st : " + aClass3.getName());System.out.println(aClass3==aClass2);}}
2.获取构造器:

定义一个类

package demo.pattern.reflect;import lombok.SneakyThrows;public class ReflectTarget {//无参构造函数public ReflectTarget() {System.out.println("公有的无参构造方法。。。");}//有参构造函数public ReflectTarget(String name) {System.out.println("带有一个参数的有参构造方法。。。,参数=" + name);}//多个参数构造方法public ReflectTarget(String name, int index) {System.out.println("带有多个参数的有参构造方法。。。,参数=" + name + "【序号】" + index);}//受保护的构造方法protected ReflectTarget(boolean n) {System.out.println("受保护的构造方法 n :" + n);}//私有构造方法private ReflectTarget(int n) {System.out.println("私有的构造方法 n :" + n);}
}
package demo.pattern.reflect;
import java.lang.reflect.Constructor;
import lombok.SneakyThrows;
public class ConstructorDemo {@SneakyThrowspublic static void main(String[] args) {Class clasz = Class.forName("demo.pattern.reflect.ReflectTarget");//获取类的实例ReflectTarget reflectTarget = (ReflectTarget)clasz.getConstructor().newInstance();//1.获取所有的公有构造方法System.out.println("**********************所有公有构造方法*********************************");Constructor[] constructors = clasz.getConstructors();for (Constructor c : constructors){System.out.println(c);}//2.取所有的构造方法(包括私有、受保护、默认、公有)System.out.println("**********************所有的构造方法(包括私有、受保护、默认、公有)*********************************");Constructor[] declaredConstructors = clasz.getDeclaredConstructors();for (Constructor c : declaredConstructors){System.out.println(c);}//3.获取单个的"公有的"构造方法System.out.println("**********************获取单个的公有的构造方法*********************************");Constructor constructor1 = clasz.getConstructor(String.class);System.out.println(constructor1);//4.获取"某个构造方法"可以是私有的,或受保护、默认、公有System.out.println("**********************获取某个构造方法可以是私有的,或受保护、默认、公有*********************************");Constructor declaredConstructor = clasz.getDeclaredConstructor(int.class);System.out.println(declaredConstructor);System.out.println("******************调用私有构造方法创建实例*******************************");//5.暴力访问(忽略掉访问修饰符)//如果是private,肯定不能被外部访问,这里直接使用暴力属性declaredConstructor.setAccessible(true);ReflectTarget o = (ReflectTarget)declaredConstructor.newInstance(1);}
}
3.获取Filed的代码:

1.类

package demo.pattern.reflect;public class ReflectTarget {public String name;protected int index;private boolean n;String age;
}

2.测试Field

package demo.pattern.reflect;import java.lang.reflect.Field;import lombok.SneakyThrows;public class FieldDemo {@SneakyThrowspublic static void main(String[] args) {Class clasz = Class.forName("demo.pattern.reflect.ReflectTarget");//1.获取所有公有的字段System.out.println("************获取所有公有的字段********************");Field[] fields = clasz.getFields();for (Field f: fields){System.out.println(f);}//2.获取所有的字段System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");Field[] fields1 = clasz.getDeclaredFields();for (Field f: fields1){System.out.println(f);}//3.获取单个特定公有的fieldSystem.out.println("*************获取公有字段并调用***********************************");Field name = clasz.getField("name");System.out.println(name);//4.给获取到的field赋值ReflectTarget objects = (ReflectTarget)clasz.getConstructor().newInstance();name.set(objects,"反射field-Name");//5.验证对应的值nameSystem.out.println("验证name : " + objects.name);//6.获取单个私有的FieldSystem.out.println("**************获取私有字段targetInfo并调用********************************");Field n = clasz.getDeclaredField("n");n.setAccessible(true);n.set(objects,true);System.out.println("验证n : " +n);}
}
4.获取Method的代码:
package demo.pattern.reflect;import lombok.SneakyThrows;public class ReflectTarget {public void show1(String s){System.out.println("调用了公有的,String参数的show1(): s = " + s);}protected void show2(){System.out.println("调用了受保护的,无参的show2()");}private String show3(int index){System.out.println("调用了私有的,并且有返回值的,int参数的show4(): index = " + index);return "success";}
}
package demo.pattern.reflect;import java.lang.reflect.Constructor;
import java.lang.reflect.Method;import lombok.SneakyThrows;public class MethodDemo {@SneakyThrowspublic static void main(String[] args) {Class clasz = Class.forName("demo.pattern.reflect.ReflectTarget");//2、获取所有公有方法System.out.println("***************获取所有的public方法,包括父类和Object*******************");Method[] methods = clasz.getMethods();for (Method method: methods){System.out.println(method);}//3、获取该类的所有方法System.out.println("***************获取所有的方法,包括私有的*******************");Method[] methods1 = clasz.getDeclaredMethods();for (Method method: methods1){System.out.println(method);}//4、获取单个公有方法System.out.println("***************获取公有的show1()方法*******************");Method s = clasz.getMethod("show1", String.class);System.out.println(s);//5、调用show1并执行ReflectTarget objects = (ReflectTarget)clasz.getConstructor().newInstance();objects.show1("1");//6、获取一个私有的成员方法System.out.println("***************获取私有的show4()方法******************");Method show3 = clasz.getDeclaredMethod("show3", int.class);show3.setAccessible(true);System.out.println(show3);show3.invoke(objects,1);}
}
5.如果类有继承
public class ReflectTarget extends ReflectTargetOrigin
public class ReflectTargetOrigin {String defaultMember = "default";public String publicMember = "public";protected String protectedMember = "protected";private String privateMember = "private";
}

5.注解使用反射:

原注解:

@Target:注解的作用目标
注解使用范围ElementType里面有type(类)Field(属性),method(方法)。。。
@Retention:注解的生命周期
RetentionPolicy有三个Source(只存在源文件中,不会在clas文件中)。
class(不仅出现在源文件中,也在编译后的class文件中)
RUNTIME(运行时有效)
@Documented:注解是否应当被包含在javaDoc中

自定义注解:

public @interface TestAnnotation {修饰符 返回值 属性名() 默认值;
}//自定义注解
@Target(ElementType.FIELD)//作用在属性上
@Retention(RetentionPolicy.RUNTIME)//运行时生效
public @interface PersonInfo {
//这里只能是方法名,不能是其他的//姓名public String name();//年龄public int age() default 19;//性别public String sex() default "男";//语言public String[] landuage();
}

注解的使用

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CourseInfo {//课程名称public String courseName();//课程标签public String courseTag();//课程简介public String courseProfile();//课程序号public int courseIndex() default 301;
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PersonInfo {//姓名public String name();//年龄public int age() default 19;//性别public String sex() default "男";//语言public String[] landuage();
}

使用注解

@CourseInfo(courseName = "spring课程",courseTag = "这是标签",courseIndex = 99,courseProfile = "这是简介")
public class CourseTest {@PersonInfo(name = "bear",landuage = {"php","java"})private String author;@CourseInfo(courseName = "java课程2",courseTag = "这是标签2",courseIndex = 103,courseProfile = "这是简介3")public void getCourseInfo(){}
}

3.通过反射获取注解里的东西

package demo.annotation;import lombok.SneakyThrows;import java.lang.annotation.Annotation;
import java.lang.reflect.Field;//通过反射来获取注解里的属性
public class AnnotationDemo {@SneakyThrowspublic static void parseTypeAnnotation(){Class clazz = Class.forName("demo.annotation.CourseTest");//这里只获取了类上面的注解,而不是成员变量和方法的注解Annotation[] annotations = clazz.getAnnotations();for (Annotation annotation : annotations){CourseInfo courseInfo =(CourseInfo)annotation;System.out.println("课程名字:"+ courseInfo.courseName()+"\n"+"课程标签:"+courseInfo.courseTag()+"\n"+"课程序号:"+courseInfo.courseIndex()+"\n"+"课程简介:"+ courseInfo.courseProfile());}}@SneakyThrowspublic static void parseFieldAnnotation(){Class clazz = Class.forName("demo.annotation.CourseTest");//解析属性上的注解Field[] declaredFields = clazz.getDeclaredFields();for (Field field : declaredFields){//判断成员变量里是否有指定类型的注解boolean annotationPresent = field.isAnnotationPresent(PersonInfo.class);if(annotationPresent){PersonInfo annotation = field.getAnnotation(PersonInfo.class);System.out.println("姓名:"+annotation.name()+"\n"+"年龄:"+annotation.age()+"\n"+"性别:"+annotation.sex());for (String language : annotation.landuage()){System.out.println("语言:"+language);}}}}//解析方法注解public static void parseMethodAnnotation() throws ClassNotFoundException{Class clazz = Class.forName("demo.annotation.ImoocCourse");Method[] methods = clazz.getDeclaredMethods();for (Method method : methods) {/** 判断方法中是否有指定注解类型的注解*/boolean hasAnnotation = method.isAnnotationPresent(CourseInfoAnnotation.class);if(hasAnnotation){CourseInfoAnnotation courseInfoAnnotation = method.getAnnotation(CourseInfoAnnotation.class);System.out.println("课程名:" + courseInfoAnnotation.courseName() + "\n" +"课程标签:" + courseInfoAnnotation.courseTag() + "\n" +"课程简介:" + courseInfoAnnotation.courseProfile() + "\n"+"课程序号:" + courseInfoAnnotation .courseIndex() + "\n");}}}public static void main(String[] args) {parseTypeAnnotation();parseFieldAnnotation();parseMethodAnnotation();}
}

总结:

通过反射获取注解的方法:@Retention(RetentionPolicy.RUNTIME)这里必须是运行状态,其他的就不能获取
//获取类上面
Annotation[] annotations = clazz.getAnnotations();
//获取属性上注解的内容
Field[] declaredFields = clazz.getDeclaredFields();
//获取方法上注解的内容
Method[] declaredMethods = clazz.getDeclaredMethods();

3.【反射机制】-spring源码学习必备知识相关推荐

  1. spring源码学习之整合Mybatis原理分析

    本文主要解析spring是如何与mybatis进行整合,整合的过程中需要哪些组件的支持.以前面提到过的配置例子<spring源码学习之aop事物标签解析> 整合的过程中需要使用以下这个依赖 ...

  2. Spring源码学习(三)-- 底层架构核心概念解析

    前面,我们大概了解了Spring中的一些概念和底层工作流程,这篇是后续看Spring源码所必备的,防止后续看源码的过程中,遇到不会的概念得单独跳出来学习.​ BeanDefinition BeanDe ...

  3. spring源码学习之路---深入AOP(终)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章和各位一起看了一下sp ...

  4. Spring源码学习的初步体会

    Spring源码学习的初步体会: 深入学习和巩固java的基础知识,其中的java知识范围全部,可以边研究源码边巩固复习基础知识 体会其中用到的设计思想:其中包含的设计原则和设计模式. 加深对spri ...

  5. 【Spring源码学习】Spring Bean的销毁

    [Spring源码学习]Spring Bean的销毁 一.注册bean销毁的类 1.registerDisposableBeanIfNecessary() 2.DisposableBeanAdapte ...

  6. Spring源码学习(四) | @Configuration的cglib动态代理

    文章目录 前言 例子 @Configuration :full or lite 设置 full or lite Cglib生成代理类AppConfig Where is it generated Ho ...

  7. Spring源码学习笔记:经典设计模式之代理模式

    1.博客内容均出自于咕泡学院架构师第三期 2.架构师系列内容:架构师学习笔记(持续更新) 0.代理模式(Proxy Pattern) 指为其他对象提供一种代理,以控制对这个对象的访问.代理对象在客户端 ...

  8. 结合Spring源码学习单例设计模式

    之前我学习了 Spring Ioc,明白了 Spring IoC 容器是一个管理Bean的容器,在Spring的定义中,它要求所有的IoC容器都需要实现接口 BeanFactory ,它是一个顶级容器 ...

  9. Spring源码学习笔记:经典设计模式之策略模式

    1.博客内容均出自于咕泡学院架构师第三期 2.架构师系列内容:架构师学习笔记(持续更新) 0.策略模式(Strategy pattern) 指定义了算法家族,分别封装起来,让它们之间可以互相替换,此模 ...

最新文章

  1. djongo:Django和MongoDB连接器
  2. php使用redis内存不足,PHP开发:Redis 内存满了怎么办?
  3. 日常生活小技巧 --惠普战66三代 重装系统
  4. SpringBoot开发案例之CountDownLatch多任务并行处理
  5. php创建多级栏目_用PHP实现多级树型菜单
  6. Expression Template(表达式模板,ET)
  7. systemd 开机无法启动privoxy
  8. VB 超简单的屏幕截图代码
  9. 数组、字符串长度的计算(转)
  10. 拓端tecdat|R语言GARCH模型对股市sp500收益率bootstrap、滚动估计预测VaR、拟合诊断和蒙特卡罗模拟可视化
  11. Solr进阶之拼写纠错功能的实现基础拼音
  12. bzoj4556(sam)
  13. wamp mysql_wamp中如何打开mysql
  14. 坐飞机时为什么不能说一路顺风
  15. 基于Matlab的数字水印设计—基于DCT域的水
  16. 苹果App卡审怎么办?
  17. 记 flip 简单的动画思路
  18. 【Python】经典问题创建一个矩形类,定义方法 属性 初始化
  19. (Python语法篇)4.序列(3)字典
  20. UOS安装mysql

热门文章

  1. List、Set、Map、Queue、Deque、Stack的遍历方式总结
  2. easyConnect无法连接到服务端,之前可以
  3. 深度应用驱动的医学知识图谱构建(二)
  4. Paint(一):画笔基本使用
  5. .DS_Store文件
  6. 4天你也可以自己处理二代三代转录组数据分析
  7. DSPE-PEG7-COOH分子量是1142.5以及其化学性质
  8. matlab油气田渗流,基于有限差分的油水兩相渗流方程求解油藏数值模拟毕业设计稿.doc...
  9. 7.MPLS VP恩 后门链路shamlink
  10. windows 2003 下如何装 Avira Antivir(小红伞)