标签:变量 ring 编程 一段 methods 示例 执行方法 构造器 符号
Reflection (反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。
是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构。
主要动态语言: Object-C. C#、JavaScript. PHP、Python、 Erlang
与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、 C、C++
。
Java不是动态语言,但Java可以称之为“准动态语言”。即Java有 ”定 的动态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。Java的动态性让编程的时候更加灵活!
java.lang.Class
:代表- 一个类java.lang.reflect.Method
:代表类的方法java.lang.reflect.Field
:代表类的成员变量java.lang.reflect.Constructor
:代表类的构造器class Person{
public int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
private Person(String name){
this.name=name;
}
public Person() {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("你好,我是"+this.name);
}
private String showNation(String nation){
System.out.println("我的国籍是"+nation);
return nation;
}
}
public class Demo01 {
public static void main(String[] args) {
//1. 创建Person类对象
Person p1=new Person(12,"Tom");
//2. 通过对象,调用其内部的属性,方法
p1.age=10;
System.out.println(p1.toString());
p1.show();
//在Person类的内部,不可以通过Person类对象调用其内部的结构
//比如:name、showNation()以及其私有的构造函数
}
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz=Person.class;//获取Person类的class类
Constructor cons=clazz.getConstructor(int.class,String.class);//通过反射获取构造器
Object obj=cons.newInstance(12,"Tom");//通过发射调用构造器创建对象
System.out.println(obj.toString());
}
效果:
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
//通过反射,调用对象的指定的属性、方法
Class clazz=Person.class;
Constructor cons=clazz.getConstructor(int.class,String.class);
Object obj=cons.newInstance(12,"Tom");
System.out.println(obj.toString());
Field name = clazz.getDeclaredField("age");
name.set(obj,10);
System.out.println(obj.toString());
}
效果:
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
//通过反射,调用对象的指定的属性、方法
Class clazz=Person.class;
Constructor cons=clazz.getConstructor(int.class,String.class);
Object obj=cons.newInstance(12,"Tom");
System.out.println(obj.toString());
Field name = clazz.getDeclaredField("age");
name.set(obj,10);
System.out.println(obj.toString());
//反射调用方法
Method show = clazz.getDeclaredMethod("show");
show.invoke(obj);
}
效果:
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
//通过反射,调用对象的指定的属性、方法
Class clazz=Person.class;
Constructor cons=clazz.getConstructor(int.class,String.class);
Object obj=cons.newInstance(12,"Tom");
System.out.println(obj.toString());
Field name = clazz.getDeclaredField("age");
name.set(obj,10);
System.out.println(obj.toString());
//反射调用方法
Method show = clazz.getDeclaredMethod("show");
show.invoke(obj);
//通过反射。可以地哦啊用Person类的私有结构,比如私有的构造器、方法、属性
Constructor constructor=clazz.getDeclaredConstructor(String.class);
constructor.setAccessible(true);
Person p2=(Person) constructor.newInstance("Jerry");
System.out.println(p2);
}
效果:
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person p1=new Person(12,"dreamcold");
Class clazz=Person.class;
//调用私有属性
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(p1,"HanMeiMei");
System.out.println(p1);
}
效果:
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Person p1=new Person(12,"dreamcold");
Class clazz=Person.class;
//调用私有属性
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(p1,"HanMeiMei");
System.out.println(p1);
//调用私有方法
Method showNation = clazz.getDeclaredMethod("showNation", String.class);
showNation.setAccessible(true);
showNation.invoke(p1,"中国");//相当于p1.showNation("中国")
}
效果:
加载到内存中的运行时类,会缓存- -定的时间。在此时间之内,我们可以通过不同的方式
来获取此运行时类。获取Class对象的三种方式:
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
//方式一:调用运行时类的属性: .class
Class clazz1=Person.class;
System.out.println(clazz1);
//方式二:通过运行时类的对象
Person p1=new Person();
Class clazz2=p1.getClass();
System.out.println(clazz2);
//方式三:调用Class的静态方法: forName(String classPath)
Class clazz3=Class.forName("com.dreamcold.thread.NumThread");
System.out.println(clazz3);
//方式四:使用类加载器: ClassLoader
ClassLoader classLoader=Person.class.getClassLoader();
Class claszz4=classLoader.loadClass("com.dreamcold.reflect.Person");
System.out.println(claszz4);
System.out.println(clazz1==claszz4);
}
效果:
外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
(2) interface: 接口
(3) []: 数组
(4) enum:枚举
(5) annotation: 注解@interface
(6) primitive type:基本数据类型
(7) void
Class c1 = object. class;
Class c2 = Comparable. class;
Class c3 = String[] .class;
Class c4 = int[][] . class;
Class c5 = ElemenitType. class;
Class c6 = Override. class;
Class c7 = int.class;
Class C8 = void.class;
Class c9 = Class. class;
int[] a = new int[10] ;
int[] b = new int[100] ;
Class c10 = a.getClass();
Class c11 =b. getClass();
//只要元素类型与维度一样,就是同一个Class
System. out. println(c10 == c11);
当程序正动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。
加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时
数据结构,然后生成-一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问
入口(即引用地址)。所有需要访问和使用类数据只能通过这个Class对象。这个加载的
过程需要类加载器参与。
<clinit>()
方法的过程。类构造器<clinit>()
方法是由编译期自动收集类中<clinit>
()方 法在多线程环境中被正确加锁和同步。pub1ic class ClassLoadingTest {
public static void main(String[] args) {
System. out .print1n(A.m);
}
class A {
static{
m =300;
}
static int m = 100;
//第二步:链接结束后m=6
//第三步:初始化后,m的值由<clinit>()方法执行决定
//这个A的类构造器<clinit>()方法由类变量的赋值和静态代码块中的语句按照顺序合并产生,类似于
<clinit>(){
m = 300;
m =100;
}
}
类加载器作用是用来把类(class)装载进内存的。JVM规范定义了如下类型的类的加载器。
引导类加载器:用C++编写的,是JMM自带的类加载器,员Java平台核心库,用来装载核心类库。该加载器无法直接获职
扩展类加战器:负责e/ibext目录下的ar包或-java.ext.dirs指定目录下的ar包装入工作库系统类加载器:负责java- classpalh或
java.class path所指的目录下的类与jar包装入工作,是最常用的加戟器
package com.dreamcold.reflect;
public class ClassLoaderTest {
public static void main(String[] args) {
//对于自定义类,使用系统类加载器进行加载
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
System.out.println(classLoader);
//调用系统类加载器的getParent():获取扩展类加载器
ClassLoader parent = classLoader.getParent();
System.out.println(parent);
//引导类加载器主要负责加载java的核心类库,无法加载自定义类的。
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
}
}
效果:
package com.dreamcold.reflect;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
public class Demo02 {
public static void main(String[] args) throws IOException {
Properties pros=new Properties();
FileInputStream fis=new FileInputStream("classload.properties");
pros.load(fis);
String name = pros.getProperty("name");
String age=pros.getProperty("age");
System.out.println("name = "+name+",password = "+age);
}
}
效果:
package com.dreamcold.reflect;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class Demo02 {
public static void main(String[] args) throws IOException {
Properties pros=new Properties();
// FileInputStream fis=new FileInputStream("classload.properties");
// pros.load(fis);
ClassLoader classLoader=ClassLoaderTest.class.getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("classload.properties");
pros.load(resourceAsStream);
String name = pros.getProperty("name");
String age=pros.getProperty("age");
System.out.println("name = "+name+",password = "+age);
}
}
效果:
原因:配置文件默认识别为:当前module的src下,配置文件放在如下的位置:
再次运行:
newInstance():调用此方法,创建对应的运行时类的对象
要想此方法正常的创建运行时类的对象,要求:
注意:
在javabean中要求提供一public 的空参构造器。原因:
package com.dreamcold.reflect;
public class NewInstanceTest {
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
Class claz=Person.class;
Object o = claz.newInstance();
System.out.println(o.toString());
}
}
效果:
该例子会随机创建对应的不同对象,体现了反射的动态性
package com.dreamcold.reflect;
import java.util.Random;
public class Demo03 {
/**
* 创建- -个指定类的对象。
* classPath:指定类的全类名
* @param args
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
int num=new Random().nextInt(3);//0,1,2
String classPath="";
switch (num){
case 0:
classPath="java.util.Date";
break;
case 1:
classPath="java.sql.Date";
break;
case 2:
classPath="com.dreamcold.reflect.Person";
break;
}
try {
Object obj=newInstance(classPath);
System.out.println(obj);
}catch (Exception e){
e.printStackTrace();
}
}
private static Object newInstance(String classPath) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
return Class.forName(classPath).newInstance();
}
}
反射提供了很多丰富的接口来帮助我们获取类的相应信息:
Person类
package com.dreamcold.reflect2;
@MyAnnoation("hi")
public class Person extends Creature<String> implements Comparable<String> ,MyInterface{
private String name;
int age;
public int id;
@MyAnnoation("abc")
public Person(){
}
private Person(String name){
this.name=name;
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
@MyAnnoation
private String show(String nation){
System.out.println("我的国籍是: "+nation);
return nation;
}
public String display(String insterest){
return insterest;
}
@Override
public void info() {
System.out.println("我是一个人");
}
@Override
public int compareTo(String o) {
return 0;
}
}
自定义注解MyAnnoation
package com.dreamcold.reflect2;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnoation {
String value() default "hello";
}
自定义接口MyInterface
package com.dreamcold.reflect2;
public interface MyInterface {
void info();
}
父类Creature
package com.dreamcold.reflect2;
import java.io.Serializable;
public class Creature<T> implements Serializable {
private char gender;
public double weight;
private void breath(){
System.out.println("生物呼吸");
}
public void eat(){
System.out.println("生物吃东西");
}
}
目录的完整结构:
示例一:获取类的所有的public方法
package com.dreamcold.reflect2;
import java.lang.reflect.Field;
public class Demo01 {
public static void main(String[] args){
Class clazz=Person.class;
//获取属性结构
//getFields():获取当前运行时类及其父类中声明为public访问权限的属性
Field[] fields = clazz.getFields();
for (Field f:fields){
System.out.println(f);
}
}
}
效果:
示例二:获取类的所有声明方法,不包括父类方法
package com.dreamcold.reflect2;
import java.lang.reflect.Field;
public class Demo01 {
public static void main(String[] args){
Class clazz=Person.class;
//getDeclaredFields():获取当前运行时类中声明的所有属性。(不包含父类 中声明的属性总
Field[] declaredFields = clazz.getDeclaredFields();
for (Field f: declaredFields){
System.out.println(f);
}
}
}
示例三:获取当前类的中属性的访问修饰、数据类型、变量名
package com.dreamcold.reflect2;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Demo02 {
public static void main(String[] args) {
Class clazz=Person.class;
Field[] declaredFields = clazz.getDeclaredFields();
for (Field f:declaredFields){
//1. 权限修饰符
int modifiers = f.getModifiers();
System.out.println(Modifier.toString(modifiers));
//2.数据类型
Class type=f.getType();
System.out.println(type);
//3.变量名
String name = f.getName();
System.out.println(name);
}
}
}
效果:
示例一:获取类中的所有的方法(包括父类)
package com.dreamcold.reflect2;
import java.lang.reflect.Method;
public class Demo03 {
public static void main(String[] args) {
Class clazz=Person.class;
//getMethods():获取当前运行时类及其所有父类中声明为public权限的方法
Method[] methods = clazz.getMethods();
for (Method m:methods){
System.out.println(m);
}
}
}
效果:
示例二:获取当前运行时类中声明的所有方法。(不包 含父类中声明的) |
package com.dreamcold.reflect2;
import java.lang.reflect.Method;
public class Demo04 {
public static void main(String[] args) {
Class clazz=Person.class;
//getDeclaredMethods(): 获取当前运行时类中声明的所有方法。(不包 含父类中声明的) |
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method m:declaredMethods){
System.out.println(m);
}
}
}
效果:
‘
示例三:获取方法的访问修饰符、返回值类型、方法名
package com.dreamcold.reflect2;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Demo05 {
public static void main(String[] args) {
Class clazz=Person.class;
Method[] declaredMethods = clazz.getDeclaredMethods();
for(Method m:declaredMethods){
//注解
Annotation[] annotations = m.getAnnotations();
for (Annotation a:annotations){
System.out.println(a);
}
//访问修饰符
System.out.println(Modifier.toString(m.getModifiers())+"\t");
//返回值类型
System.out.println(m.getReturnType().getName()+"\t");
//函数名
System.out.println(m.getName()+"\t");
//参数列表
System.out.print("(");
Class[] parameterTypes = m.getParameterTypes();
if (parameterTypes!=null){
for (int i=0;i<parameterTypes.length;i++){
if (i==parameterTypes.length-1){
System.out.print(parameterTypes[i].getName()+"args_"+i);
}
System.out.print(parameterTypes[i].getName()+"args_"+i+",");
}
}
System.out.print(")");
//抛出的异常
Class[] exceptionTypes = m.getExceptionTypes();
if (exceptionTypes.length>0){
for (int i = 0; i < exceptionTypes.length; i++) {
if (i==exceptionTypes.length-1){
System.out.println(exceptionTypes[i].getName());
break;
}
System.out.println(exceptionTypes[i].getName()+",");
}
}
System.out.println();
}
}
}
效果:
示例一:getConstructors():获取当前运行时类中声明为public的构造器
package com.dreamcold.reflect2;
import java.lang.reflect.Constructor;
public class Demo06 {
public static void main(String[] args){
Class clazz=Person.class;
Constructor[] constructors = clazz.getConstructors();
for (Constructor c:constructors){
System.out.println(c);
}
}
}
效果:
package com.dreamcold.reflect2;
import java.lang.reflect.Constructor;
public class Demo06 {
public static void main(String[] args){
Class clazz=Person.class;
Constructor[] constructors = clazz.getConstructors();
for (Constructor c:constructors){
System.out.println(c);
}
}
}
效果:
示例二:getDeclaredConstructors():获取当前运行时类中声明的所有的构造器
package com.dreamcold.reflect2;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Demo06 {
public static void main(String[] args){
Class clazz=Person.class;
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor constructor:declaredConstructors){
System.out.println(constructor);
}
}
}
效果:
示例一:获取运行时的父类
package com.dreamcold.reflect2;
public class Demo07 {
public static void main(String[] args) {
Class clazz=Person.class;
Class superclass = clazz.getSuperclass();
System.out.println(superclass);
}
}
效果:
’
示例二:获取运行的时候带泛型的父类
package com.dreamcold.reflect2;
import java.lang.reflect.Type;
public class Demo08 {
public static void main(String[] args) {
Class clazz=Person.class;
Type genericSuperclass = clazz.getGenericSuperclass();
System.out.println(genericSuperclass);
}
}
效果:
示例三:获取运行的时候带泛型的父类,带的参数的类型
package com.dreamcold.reflect2;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class Demo08 {
public static void main(String[] args) {
Class clazz=Person.class;
//获取泛型的类型
Type genericSuperclass = clazz.getGenericSuperclass();
ParameterizedType paramType=(ParameterizedType)genericSuperclass;
Type[] actualTypeArguments = paramType.getActualTypeArguments();
System.out.println(actualTypeArguments[0].getTypeName());
}
}
效果:
package com.dreamcold.reflect2;
public class Demo09 {
public static void main(String[] args) {
Class clazz=Person.class;
Class[] interfaces = clazz.getInterfaces();
for (Class c:interfaces){
System.out.println(c);
}
System.out.println();
Class[] interfaces1 = clazz.getSuperclass().getInterfaces();
for (Class c:interfaces1){
System.out.println(c);
}
}
}
效果:
package com.dreamcold.reflect2;
import java.lang.annotation.Annotation;
public class Demo10 {
public static void main(String[] args) {
Class clazz=Person.class;
Package aPackage = clazz.getPackage();
System.out.println(aPackage);
}
}
效果:
package com.dreamcold.reflect2;
import java.lang.annotation.Annotation;
public class Demo10 {
public static void main(String[] args) {
Class clazz=Person.class;
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation:annotations){
System.out.println(annotation);
}
}
}
结果:
调用运行时类中指定的结构:属性、方法、构造器
示例一:获取和设置运行时类中的属性
package com.dreamcold.reflect2;
import java.lang.reflect.Field;
public class Demo11 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
Class clazz=Person.class;
//创建运行时的对象
Person p =(Person) clazz.newInstance();
//获取指定的属性
Field id=clazz.getField("id");
//设置当前属性的值
//set():参数
//参数1指明那个对象的属性,参数2:将此属性设置为多少
id.set(p,1001);
//获取当前属性的值,要求运行时类中的属性声明为public
//通常不采用此方法
int pId = (int)id.get(p);
System.out.println(pId);
}
}
效果:
示例二:获取和设置运行时类中的属性(实际开发中使用)
package com.dreamcold.reflect2;
import java.lang.reflect.Field;
public class Demo12 {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchFieldException {
Class clazz=Person.class;
//创建运行时的对象
Person p =(Person) clazz.newInstance();
//getDeclaredField获取运行时类中的指定变量名的属性
Field name = clazz.getDeclaredField("name");
//java.lang.IllegalAccessException,由于权限不够,在set的时候报错,只有设置为public的属性才可以访问
//强制设置其可以访问后可以得到结果
name.setAccessible(true);
name.set(p,"Tom");
System.out.println(name.get(p));
}
}
效果:
示例一:调用类中的非静态方法
package com.dreamcold.reflect2;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo13 {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class clazz=Person.class;
//创建运行时的对象
Person p =(Person) clazz.newInstance();
//1. 获取指定的某个方法getDeclaredMethod,指明获取的方法的名称 参数2:指明获取方法的形参列表中的class
Method show = clazz.getDeclaredMethod("show", String.class);
//java.lang.IllegalAccessException会被报出,如果不是public方法的情况下,所以要设置可访问
//invoke()的返回值即为对应方法的返回值
show.setAccessible(true);
//2. invoke():参数1 方法的调用者 参数2:给方法形参赋值的实参
show.invoke(p,"china");
}
}
效果:
示例二:调用类中的非静态方法,在Person类中加入一个静态方法
private static void showDesc(){
System.out.println("我是一个可爱的人");
}
Test.java
package com.dreamcold.reflect2;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo14 {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class clazz=Person.class;
//创建运行时的对象
Person p =(Person) clazz.newInstance();
Method showDesc = clazz.getDeclaredMethod("showDesc");
showDesc.setAccessible(true);
Object invoke = showDesc.invoke(null);
System.out.println(invoke);//null
}
}
效果:
package com.dreamcold.reflect2;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Demo15 {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class clazz=Person.class;
//创建运行时的对象
Person p =(Person) clazz.newInstance();
//1.获取指定的构造器
//getDeclaredConstructor():参数:指明构造器的参数列表
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
//2.保证此构造器是可访问的
declaredConstructor.setAccessible(true);
//3.调用此构造器创建运行时类的对象
Person tom =(Person) declaredConstructor.newInstance("Tom");
System.out.println(tom.toString());
}
}
效果:
为什么叫静态代理:特点:代理类和被代理类在编译期间,就确定下来了。
package com.dreamcold.reflect2;
/**
* 静态代理举例
*/
interface ClothFactory{
void produceCloth();
}
//代理类
class ProxyClothFactory implements ClothFactory{
private ClothFactory factory;//就用被代理类的对象进行实例化
public ProxyClothFactory(ClothFactory clothFactory){
this.factory=clothFactory;
}
@Override
public void produceCloth() {
System.out.println("代理工厂做一些准备工作");
factory.produceCloth();
System.out.println("代理工厂还要做一些后续的收尾工作");
}
}
//被代理类
class NikeClothFactory implements ClothFactory{
@Override
public void produceCloth() {
System.out.println("Nike工厂生产一批运动服");
}
}
public class StaticProxyTest {
public static void main(String[] args) {
//创建被代理的对象
NikeClothFactory nike=new NikeClothFactory();
//代理类的创建
ClothFactory proxyClothFactory = new ProxyClothFactory(nike);
proxyClothFactory.produceCloth();
}
}
效果:
package com.dreamcold.reflect2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Human{
String getBelief();
void eat(String food);
}
//被代理类
class SuperMan implements Human{
@Override
public String getBelief() {
return "I believe I can fly!";
}
@Override
public void eat(String food) {
System.out.println("我喜欢吃"+food);
}
}
/**
* 要想实现动态代理,需要解决什么问题?
* 问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类以及对象?
* 问题二:当通过代理类的对象调用方法的时候,如何动态的调用被代理类中的同名方法
*/
class MyInvocationHandler implements InvocationHandler {
//需要使用被代理类的对象进行赋值,因为invoke方法要作用在一个对象上,所以在这里要声明
private Object obj;
public void bind(Object obj){
this.obj=obj;
}
//当我们通过代理类对象调用方法a的时候,就会自动调用如下的方法invoke()
//将被代理类要执行的方法a的功能就声明在invoke()中
//第一个参数是代理类的对象
//第二个是代理类的对象调用的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//method:即为代理类对象调用的方法方法,此方法也就作为了被代理对象要刁颖的方法
//obj:被代理类的对象
Object returnValue = method.invoke(obj, args);
//上述方法的返回值就作为当前类中的invoke()的返回值
return returnValue;
}
}
class ProxyFactory{
//调用词方法,返回一个代理类的对象
public static Object getProxyInstance(Object obj){//obj:被代理的类
//使用Proxy类的newProxyInstance方法来创建代理类的对象
//第一个参数是类的加载器
//第二个参数是接口,也就是代理类和被代理类共同要实现的接口
//第三个参数是叫做InvocationHandler,是解决以上两个问题中第二个问题的
MyInvocationHandler myInvocationHandler=new MyInvocationHandler();
//相当于对obj的赋值
myInvocationHandler.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),myInvocationHandler);
}
}
public class ProxyTest {
public static void main(String[] args) {
//创建代理类对象
SuperMan superMan = new SuperMan();
//proxyInstance:代理类的对象
Human proxyInstance =(Human) ProxyFactory.getProxyInstance(superMan);
////当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法
System.out.println(proxyInstance.getBelief());;
proxyInstance.eat("四川麻辣烫");
}
}
效果:
前面介绍的Proxy和InvocationHandler,很难看出这种动态代理的优势,下面介绍-种更实用的动态代理机制
改进后的说明:代码段1、代码段2、代码段3和深色代码段分离开了,但代码段1、2、3又和一个特定的方法A耦合了!最理想的效果是:代码块1、2、3既可以执行方法A,又无须在程序中以硬编码的方式直接调用深色代码的方法
中间灰色的方法可以想象是动态的,想放那个方法放那个方法
package com.dreamcold.reflect2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Human{
String getBelief();
void eat(String food);
}
//被代理类
class SuperMan implements Human{
@Override
public String getBelief() {
return "I believe I can fly!";
}
@Override
public void eat(String food) {
System.out.println("我喜欢吃"+food);
}
}
//用来体现AOP
class HumanUtil{
public void method1(){
System.out.println("通用方法一");
}
public void method2(){
System.out.println("通用方法二");
}
}
/**
* 要想实现动态代理,需要解决什么问题?
* 问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类以及对象?
* 问题二:当通过代理类的对象调用方法的时候,如何动态的调用被代理类中的同名方法
*/
class MyInvocationHandler implements InvocationHandler {
//需要使用被代理类的对象进行赋值,因为invoke方法要作用在一个对象上,所以在这里要声明
private Object obj;
public void bind(Object obj){
this.obj=obj;
}
//当我们通过代理类对象调用方法a的时候,就会自动调用如下的方法invoke()
//将被代理类要执行的方法a的功能就声明在invoke()中
//第一个参数是代理类的对象
//第二个是代理类的对象调用的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
HumanUtil humanUtil=new HumanUtil();
humanUtil.method1();
//method:即为代理类对象调用的方法方法,此方法也就作为了被代理对象要刁颖的方法
//obj:被代理类的对象
Object returnValue = method.invoke(obj, args);
//上述方法的返回值就作为当前类中的invoke()的返回值
humanUtil.method2();
return returnValue;
}
}
class ProxyFactory{
//调用词方法,返回一个代理类的对象
public static Object getProxyInstance(Object obj){//obj:被代理的类
//使用Proxy类的newProxyInstance方法来创建代理类的对象
//第一个参数是类的加载器
//第二个参数是接口,也就是代理类和被代理类共同要实现的接口
//第三个参数是叫做InvocationHandler,是解决以上两个问题中第二个问题的
MyInvocationHandler myInvocationHandler=new MyInvocationHandler();
//相当于对obj的赋值
myInvocationHandler.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),myInvocationHandler);
}
}
public class ProxyTest {
public static void main(String[] args) {
//创建代理类对象
SuperMan superMan = new SuperMan();
//proxyInstance:代理类的对象
Human proxyInstance =(Human) ProxyFactory.getProxyInstance(superMan);
////当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法
System.out.println(proxyInstance.getBelief());;
proxyInstance.eat("四川麻辣烫");
}
}
效果:
我们发现在原来每个执行的方法前后都加上了对应的HumanUtil中的方法执行
标签:变量 ring 编程 一段 methods 示例 执行方法 构造器 符号
原文地址:https://www.cnblogs.com/mengxiaoleng/p/14759731.html