导航:首页 > 编程语言 > java反射与动态代理

java反射与动态代理

发布时间:2023-07-10 10:55:54

㈠ 什么是反射技术什么是静态代理什么是动态代理什么是aop

java的静态代理与动态代理比较 一、概念 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。按照代理类的创建时期,代理类可分为两种。 静态代理类: 由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理类:在程序运行时,运用反射机制动态创建而成。 二、静态代理类 如下, HelloServiceProxy 类是代理类,HelloServiceImpl类是委托类,这两个类都实现了HelloService接口。其中HelloServiceImpl类是HelloService接口的真正实现者,而HelloServiceProxy类是通过调用HelloServiceImpl 类的相关方法来提供特定服务的。HelloServiceProxy类的echo()方法和getTime()方法会分别调用被代理的HelloServiceImpl 对象的echo()方法和getTime()方法,并且在方法调用前后都会执行一些简单的打印操作。 由此可见,代理类可以为委托类预处理消息、把消息转发给委托类和事后处理消息等。 例程1 HelloService.java package proxy; import java.util.Date; public interface HelloService{ public String echo(String msg); public Date getTime(); } 例程2 HelloServiceImpl.java package proxy; import java.util.Date; public class HelloServiceImpl implements HelloService{ public String echo(String msg){ return "echo:"+msg; } public Date getTime(){ return new Date(); } } 例程3 HelloServiceProxy.java package proxy; import java.util.Date; public class HelloServiceProxy implements HelloService{ private HelloService helloService; //表示被代理的HelloService 实例 public HelloServiceProxy(HelloService helloService){ this.helloService=helloService; } public void setHelloServiceProxy(HelloService helloService){ this.helloService=helloService; } public String echo(String msg){ System.out.println("before calling echo()"); //预处理 String result=helloService.echo(msg); //调用被代理的HelloService 实例的echo()方法 System.out.println("after calling echo()"); //事后处理 return result; } public Date getTime(){ System.out.println("before calling getTime()"); //预处理 Date date=helloService.getTime(); //调用被代理的HelloService 实例的getTime()方法 System.out.println("after calling getTime()"); //事后处理 return date; } } 在Client1 类的main()方法中,先创建了一个HelloServiceImpl对象,又创建了一个HelloServiceProxy对象,最后调用HelloServiceProxy对象的echo()方法。 例程4 Client1.java package proxy; public class Client1{ public static void main(String args[]){ HelloService helloService=new HelloServiceImpl(); HelloService helloServiceProxy=new HelloServiceProxy(helloService); System.out.println(helloServiceProxy.echo("hello")); } } 运行Client1 类,打印结果如下: before calling echo() after calling echo() echo:hello 例程3 的HelloServiceProxy 类的源代码是由程序员编写的,在程序运行前,它的.class文件就已经存在了,这种代理类称为静态代理类。 三、动态代理类 与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。 Proxy类提供了创建动态代理类及其实例的静态方法。 (1)getProxyClass()静态方法负责创建动态代理类,它的完整定义如下: public static Class<?> getProxyClass(ClassLoader loader, Class<?>[] interfaces) throws IllegalArgumentException 参数loader 指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口。 (2)newProxyInstance()静态方法负责创建动态代理类的实例,它的完整定义如下: public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler) throws IllegalArgumentException 参数loader 指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口,参数handler 指定与动态代理类关联的 InvocationHandler 对象。 以下两种方式都创建了实现Foo接口的动态代理类的实例: /**** 方式一 ****/ //创建InvocationHandler对象 InvocationHandler handler = new MyInvocationHandler(...); //创建动态代理类 Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class }); //创建动态代理类的实例 Foo foo = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }). newInstance(new Object[] { handler }); /**** 方式二 ****/ //创建InvocationHandler对象 InvocationHandler handler = new MyInvocationHandler(...); //直接创建动态代理类的实例 Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[] { Foo.class }, handler); 由Proxy类的静态方法创建的动态代理类具有以下特点: 动态代理类是public、final和非抽象类型的; 动态代理类继承了java.lang.reflect.Proxy类; 动态代理类的名字以“$Proxy”开头; 动态代理类实现getProxyClass()和newProxyInstance()方法中参数interfaces指定的所有接口; Proxy 类的isProxyClass(Class<?> cl)静态方法可用来判断参数指定的类是否为动态代理类。只有通过Proxy类创建的类才是动态代理类; 动态代理类都具有一个public 类型的构造方法,该构造方法有一个InvocationHandler 类型的参数。 由Proxy类的静态方法创建的动态代理类的实例具有以下特点: 1. 假定变量foo 是一个动态代理类的实例,并且这个动态代理类实现了Foo 接口,那么“foo instanceof Foo”的值为true。把变量foo强制转换为Foo类型是合法的: (Foo) foo //合法 2.每个动态代理类实例都和一个InvocationHandler 实例关联。Proxy 类的getInvocationHandler(Object proxy)静态方法返回与参数proxy指定的代理类实例所关联的InvocationHandler 对象。 3.假定Foo接口有一个amethod()方法,那么当程序调用动态代理类实例foo的amethod()方法时,该方法会调用与它关联的InvocationHandler 对象的invoke()方法。 InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法: Object invoke(Object proxy,Method method,Object[] args) throws Throwable 参数proxy指定动态代理类实例,参数method指定被调用的方法,参数args 指定向被调用方法传递的参数,invoke()方法的返回值表示被调用方法的返回值。 四、最后看一个实例: HelloServiceProxyFactory 类的getHelloServiceProxy()静态方法负责创建实现了HelloService接口的动态代理类的实例。 例程5 HelloServiceProxyFactory.java package proxy; import java.lang.reflect.*; public class HelloServiceProxyFactory { /** 创建一个实现了HelloService 接口的动态代理类的实例 * 参数helloService 引用被代理的HelloService 实例 */ public static HelloService getHelloServiceProxy(final HelloService helloService){ //创建一个实现了InvocationHandler接口的匿名类的实例 InvocationHandler handler=new InvocationHandler(){ public Object invoke(Object proxy,Method method,Object args[])throws Exception{ System.out.println("before calling "+method); //预处理 Object result=method.invoke(helloService,args); //调用被代理的HelloService 实例的方法 System.out.println("after calling "+method); //事后处理 return result; } }; Class classType=HelloService.class; return (HelloService)Proxy.newProxyInstance(classType.getClassLoader(), new Class[]{classType}, handler); } } 如下所示的Client2 类先创建了一个HelloServiceImpl 实例,然后创建了一个动态代理类实例helloServiceProxy,最后调用动态代理类实例的echo()方法。 例程6 Client2.java package proxy; public class Client2{ public static void main(String args[]){ HelloService helloService=new HelloServiceImpl(); HelloService helloServiceProxy=HelloServiceProxyFactory.getHelloServiceProxy(helloService); System.out.println("动态代理类的名字为"+helloServiceProxy.getClass().getName()); System.out.println(helloServiceProxy.echo("Hello")); } } 运行Client2,打印结果如下: 动态代理类的名字为$Proxy0 before calling public abstract java.lang.String proxy.HelloService.echo(java.lang.String) after calling public abstract java.lang.String proxy.HelloService.echo(java.lang.String) echo:Hello 从结果看出,动态代理类的名字为$Proxy0。

㈡ java中的反射机制是什么,有什么作用啊

Method类中的方法的使用(含代码和注释):

getMethods()获得本类及父类中的public权限修饰**符方法
getDeclaredMethods()专门获得调用该方法的对象的本类中的所有方法包括private权限修饰符**的方法
getDeclaredMethod(Stringname,class<?>...parameterTypes)
第一个参数:方法的名称
第二个参数:可变长度,写你要查找的那个方法的参数类型列表.class
getParameterCount()得到方法的参数个数123456
packageLessonForReflection03;importjava.lang.reflect.Method;importjava.lang.reflect.Modifier;abstractclassCard{
privatevoidcreatRandomNumbers(intcount)//private关键字
{

}

publicvoidgetFullCardsNumbers(String[]random,Stringpre_numbers)
{

}

publicstaticvoidgetUserInfor()
{

}

(Stringtel);

(intsal1,intsal2),ArithmeticException;}publicclassMethodInforGetter{

publicstaticvoidmain(String[]args)
{
Class<?>c1=Card.class;

System.out.println("-------------------------");

Method[]m1=c1.getMethods();//getMethods()获得本类及父类中的public方法!
for(Methodm:m1)
{
System.out.println(m);
}

System.out.println("-------------------------");

Method[]m2=c1.getDeclaredMethods();//getDeclaredMethods()专门获得本类中的所有方法包括private!
for(Methodm:m2)
{
System.out.println(m);
}

System.out.println("-------------------------");

/*
*getDeclaredMethod(Stringname,class<?>...parameterTypes)
*第一个参数:方法的名称
*第二个参数:可变长度,写你要查找的那个方法的参数类型列表
*
*getParameterCount()得到方法的参数个数
*/

try
{
Methodm3=c1.getDeclaredMethod("getUserInfor");
System.out.println(m3);

//getParameterCount()方法,获得方法参数个数
System.out.println(m3.getParameterCount());
System.out.println(Modifier.toString(m3.getModifiers()));//获得方法修饰符
System.out.println(m3.getReturnType());

System.out.println("-------------------------");

Methodm4=c1.getDeclaredMethod("getUserInfor",int.class,int.class);

//getExceptionTypes()可以获得初始化当前Method对象的给Class对象初始化的那个类的那个指定方法抛出的异常类型
Class<?>[]exception=m4.getExceptionTypes();
for(Class<?>e:exception)
{
System.out.println(e);
}

}catch(NoSuchMethodException|SecurityExceptione)
{
e.printStackTrace();
}
}}576777879808182838485868788

Constructor类中的方法的使用www.xiaoyuani.com(含代码和注释):

java.lang.reflect.Constructor:
Constructor[]getConstructor()获得本类里的public权限修饰符构造函数,不能获取父类的!
Constructor[]getDeclaredConstructor()获得本类中的所以构造函数!
Constructor<T>getConstructor(Class...parameterType)用参数决定获得本类中的某个的构造方法,只能获得public的
Constructor<T>getDeclaredConstructor(Class...parameterType)用参数决定获得本类中的某个构造方法
附:
JDK8.0之后新增的类:
Executable:
它是Method和Constructor的父类
常用方法:
getParameter()获得类中方法参数
getExceptionTypes()获得类中某个方法抛出异常类型
getMoidfiers()获得方法权限修饰符
Parameter:
封装并代表了参数实例123456789101112131415
packageLessonForReflection03;importjava.lang.reflect.Constructor;importjava.lang.reflect.Modifier;importjava.lang.reflect.Parameter;/*
*java.lang.reflect.Constructor
*
*Constructor[]getConstructor();获得本类里的public权限修饰符构造函数,不能获取父类的
*Constructor[]getDeclaredConstructor();得本类里的全部构造
*
*Constructor<T>getConstructor(Class...parameterType);用参数决定获得哪个构造方法
*Constructor<T>getDeclaredConstructor(Class...parameterType);
*
*/{
publicstaticvoidmain(String[]args)
{
System.out.println("获得Cricle本类里的public权限修饰符构造函数,不能获取父类的Constructor[]getConstructor()");
System.out.println("子类继承不了父类中的构造方法和private");
//Constructor[]getConstructor()获得Cricle本类里的public权限修饰符构造函数,不能获取父类的
//子类继承不了父类中的构造方法和private
Class<Circle>c1=Circle.class;
Constructor<?>[]cons1=c1.getConstructors();
for(Constructor<?>cons:cons1)
{
System.out.println(cons);
//System.out.println(cons.getName());
}

System.out.println("-----------------------");

System.out.println("方法获得本类中的所有构造函数getDeclaredConstructor()");
Constructor<?>[]cons2=c1.getDeclaredConstructors();
for(Constructor<?>cons:cons2)
{
System.out.println(cons);
}

System.out.println("-----------------------");

try
{
System.out.println("方法用参数指定获得本类!构造方法,只能获取public的Constructor<T>getConstructor(Class...parameterType)");
Constructor<?>cons3=c1.getConstructor(int.class);
System.out.println(Modifier.toString(cons3.getModifiers()));
System.out.println(cons3);

System.out.println("-----------------------");

System.out.println("方法用参数指定获得本类!构造方法任何权限修饰符的都可以获得Constructor<T>getDeclaredConstructor(Class...parameterType)");
Constructor<?>cons4=c1.getDeclaredConstructor(String.class);
System.out.println(cons4);

System.out.println("-----------------------");

/*
*JDK8.0之后新增的类
*Executable:
*是Method和Constructor的父类
*方法:
*getParameter();
*getExceptionTypes();
*getModifiers();
*getTypeParameters();
*
*Parameter:
*封装并代表了参数实例
*/
System.out.println("获取类中方法的参数getParameters()");
Constructor<?>cons5=c1.getDeclaredConstructor(int.class,String.class);
Parameter[]p1=cons5.getParameters();
for(Parameterp:p1)
{
System.out.println(p);
}
}catch(NoSuchMethodException|SecurityExceptione)
{
e.printStackTrace();
}

}}5767778798081828384858687

代码中提到的Circle类和Shape类二者为继承关系:

packageLessonForReflection03;publicclassCircleextendsShape{
privateintr;
privateStringcolor;

publicCircle(intr,Stringcolor)
{
super();
this.r=r;
this.color=color;
}

publicCircle(intr)
{
super();
this.r=r;
}

protectedCircle(Stringcolor)
{
super();
this.color=color;
}

Circle()
{
super();
}}
packageLessonForReflection03;publicclassShape{
privateintper;

publicShape(intper)
{
super();
this.per=per;
}

publicShape()
{
super();
}}1234567891011121314151617

部分文字来源于:
咕嘟咖啡杨海滨老师 — 《java编程语言高级特性》
轻量化研习Java相关技术倡导者
“爱码学院”联合创始人自适应教学理念提出者践行者;多年开发及项目管理经历;出版《JavaEE企业级应用与开发》一书;10余年高校项目实践毕设指导经验;企业软培经验丰富

㈢ JAVA中反射是什么

JAVA中反射是动态获取信息以及动态调用对象方法的一种反射机制。

Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态语言的一个关键性质。

Java反射的功能是在运行时判断任意一个对象所属的类,在运行时构造任意一个类的对象,在运行时判断任意一个类所具有的成员变量和方法,在运行时调用任意一个对象的方法,生成动态代理。

(3)java反射与动态代理扩展阅读:

JAVA中反射实例:

1、Class superClass=clazz.getSuperclass();//获取父类。

System.out.println("getSuperclass:"+superClass)。

2、Class[] interfaces=clazz.getInterfaces();//获取实现接口。

System.out.println("getInterfaces:"+interfaces.length)。

3、Constructor[] cons=clazz.getConstructors();//构造方法。

System.out.println("getConstructors:"+cons.length)。

参考资料来源:网络: JAVA反射机制

㈣ Java的反射到底有什么用途

反射的作用可谓是博大精深,

  1. JDK动态代理生成代理类的字节码后,首先把这个类通过defineclass定义成一个类,然后用class.for(name)会把该类加载到jvm,之后我们就可以通过,A.class.GetMethod()获取其方法,然后通过invoke调用其方法,在调用这个方法时,实际上会通过被代理类的引用再去调用原方法。

  2. Java反射包reflection提供对Class,Method,field,constructor1 等信息的封装类型

  3. 通过这些api可以轻易获得一个类的各种信息并且可以进行实例化,方法调用等。
    类中的private参数可以通过setaccessible方法强制获取。

㈤ java中什么是反射,反射怎么用,什么场景用有没有替代方案

1、反射简言之就是在编译时无法拿到某一个类,但是可以在运行时动态获取这个类,这样去使用某一个类,就是反射的使用场景。
2、代替反射或者类似的操作,可以通过DI实现IOC .依赖注入,动态代理。

阅读全文

与java反射与动态代理相关的资料

热点内容
如何验证web服务器是否正常工作 浏览:132
全球最大的加密货币网站 浏览:284
解压文件为什么有问号 浏览:389
php考试系统模板 浏览:431
pdf导出图片模糊 浏览:610
我的世界编玩边学服务器地址 浏览:456
基于单片机的火灾报警系统 浏览:166
上海追星用什么app 浏览:425
海马m5压缩机维修 浏览:98
抖音怎么给自己喜欢的加密 浏览:247
中国五大加密货币 浏览:263
程序员手疼7年查6处骨肿瘤 浏览:39
python列表对象的创建与删除 浏览:467
python删除excel表格中的一行 浏览:521
android数据库的增删改查 浏览:632
云服务器2g4g有什么区别 浏览:324
显示文件夹所有文件的文件名函数 浏览:213
可以在网站写代码的编译器 浏览:76
王者换服务器怎么不用重玩 浏览:328
武汉编译ipfs云存储器 浏览:52