接上一部分,这里主要说三个部分,一个是关于反射的源头Class类,接下来是代理,一个是静态代理,一个是动态代理。基于反射机制的主要是动态代理,我自己对动态代理也不熟悉,所以这里也一并学习一下。
Class类:
首先是说明java的运行机制:普通的类经过编译后生成.class文件。java虚拟机加载.class文件,之后该.class文件加载到内存后,就是一个运行时类,该运行时类就是一个Class实例。这里说明一下每个运行时类只加载一次,也就是说以下运行结果全部为真:
Class clazz1=Person.class;//第一种
Person p=new Person();//第二种getClass
Class clazz2=p.getClass();
System.out.println(clazz2.getName());
String classname="refection.Person";//第三种Class的静态方法获取,动态性
Class clazz3=Class.forName(classname);
System.out.println(clazz1==clazz2);
System.out.println(clazz2==clazz3);
当然上面的代码也写出了获取Class实例的三种方式:第一四.class获取,第二种是getClass()函数获取,第三种是一种动态性的获取,就是通过类的名字字符串获取,给一个什么样的字符串获取他的Class,当然必须有这个类,不然抛异常。
特别说明,我们通过反射获取Class实例之后,可以做的一些事情,上一篇也说了很多任意,这里说一下大致的几种,很多方法上一篇都写到了,这里不再代码示例了。
得到Class的实例之后,我们可以做以下事情:
* 1*创建对应的运行时对象(例如Person对象)
* 2可以获取该类的完整结构(属性,方法,构造器,父类等等)
* 3*调用对应的运行时类的结构(方法,属性,构造器等等)
* 4反射应用:动态代理
下面说说代理,这里代理的原理和两个概念我直接在尚硅谷的教学视频中截的图片。
静态代理:
被代理类和代理类具有相同的父类(一般是接口),都要实现接口方法,而且代理类和接口基本上实现一对一的功能限定。一个新的接口就得重新设计代理类。
这里的举例:富士康只能生产手机,我们提供一个手机生产的接口,其他手机厂商实现接口,富士康也要实现手机生产接口,这样富士康就能为手机代工。
代码如下:
interface PhoneMake
{
/*
* 定义造手机方法
*/
public void makephone();
}
/*
* 小米手机厂商
*/
class MiPhoneMake implements PhoneMake
{
@Override
public void makephone() {
System.out.println("小米出了一批新手机");
}
}
/*
* 富士康代工厂
*/
class FuShiKang implements PhoneMake
{
/*
* 定义一个制造手机接口的对象
* 通过构造方法传入具体的被代理对象
* 实现控制被代理类的执行
*/
PhoneMake phone;
public FuShiKang(PhoneMake phone)
{
this.phone=phone;
}
@Override
public void makephone() {
System.out.println("富士康开始赶工啦");
phone.makephone();
}
}
public class ProxyPhone {
public static void main(String[] args) {
MiPhoneMake mi=new MiPhoneMake();//创建被代理对象
FuShiKang fsk=new FuShiKang(mi);//创建代理类的对象
fsk.makephone();
}
}
倘若让富士康生产衣服,这个代理肯定就得重写。如果类型多了,就更麻烦。所以引入动态代理。
动态代理
就是可以你给我什么样子的接口,我都能给你实现代理的这样一种类。
直接上代码吧,注释写的非常详细:
//手机制造接口
interface PhoneMake
{
public void makePhone();
}
//手机制造被代理类
class iPhoneMake implements PhoneMake
{
@Override
public void makePhone() {
System.out.println("iPhone10s要造出来啦");
}
}
//动态代理类
class MyInvocationHandler implements InvocationHandler
{
Object obj;
/*
* 这里定义一个函数
* 1 实现对被代理的对象实例化
* 2 返回一个代理类的对象
* @return 中的三个参数,第一个是被代理类的ClassLoader,第二个是需要执行的接口,第三个是实现了InvocationHandler的对象
*/
public Object initabc(Object obj)
{
this.obj=obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),this);
}
/*
* 通过代理类对象调用被代理类方法时,都会转入调用invoke方法
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object returnVale=method.invoke(obj, args);//调用被代理类
return returnVale;
}
}
public class ProxyTest {
public static void main(String[] args)
{
//代理手机
iPhoneMake iphone=new iPhoneMake();
MyInvocationHandler my=new MyInvocationHandler();
Object obj=my.initabc(iphone);
PhoneMake pst=(PhoneMake) obj;
pst.makePhone();
//鞋子代理
LiNingShoesMake lining=new LiNingShoesMake();
ShoesMake sho=(ShoesMake) my.initabc(lining);
sho.makeShoes();
}
}
//鞋子制造接口
interface ShoesMake
{
public void makeShoes();
}
//鞋子制造被代理类
class LiNingShoesMake implements ShoesMake
{
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void makeShoes() {
<span style="white-space:pre"> </span>System.out.println("李宁新款正在制造");
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>}
}
这里定义的动态代理,不仅可以代理手机生产,还可以代理衣服制造,通过代理类对被代理的对象方法进行调用,代理类会自动转打调用invoke方法,在这个方法里面调用被代理类的方法。这样应该比较容易理解了。