【Java反射以及代理模式】

Java反射以及代理模式

Java反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

/*
	获取Class类型对象的三种方式
*/
import java.util.Date;

public class ReflectTest01
{
	public static void main(String[] args) throws Exception{

		//第一种方式:
		Class c1 = Class.forName("Employee"); //c1引用保存内存地址指向堆中的对象,该对象代表的是Employee整个类.

		//第二种方式:
		//java中每个类型都有 class 属性.
		Class c2 = Employee.class;

		//第三种方式:
		//java语言中任何一个java对象都有 getClass 方法
		Employee e = new Employee();
		Class c3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)
		
		//因为Employee这个类在JVM中只有一个,所以c1,c2,c3的内存地址是相同的,指向堆中唯一的一个对象.
		System.out.println(c1==c2); //true
		System.out.println(c2==c3); //true

		
		//c4,c5,c6都代表 Date这个类
		Class c4 = Date.class; //c4代表 Date这个类

		Class c5 = Class.forName("java.util.Date"); //必须写类全名,类全名带有包名.

		Date d = new Date();
		Class c6 = d.getClass();
		
		System.out.println(c4==c5); //true
		System.out.println(c5==c6); //true

		//c7代表 int 类型
		Class c7 = int.class;

	}
}

/*
	获取某个特定的构造方法,然后创建对象.
*/
import java.lang.reflect.*;

public class ReflectTest09
{
	public static void main(String[] args) throws Exception{
		
		//1.获取类
		Class c = Class.forName("Customer");


		//2.获取特定的构造方法
		Constructor con = c.getDeclaredConstructor(String.class,int.class);

		//3.创建对象
		Object o = con.newInstance("张三",25);

		System.out.println(o);


	}
}

class Customer
{
	String name;
	int age;

	Customer(String name,int age){
		this.name = name;
		this.age = age;
	}

	public String toString(){
		return "Customer["+name+","+age+"]";
	}
}

/*
	java.lang.reflect.Field; 获取某个指定的属性
*/
import java.lang.reflect.*;
public class ReflectTest05
{
	public static void main(String[] args) throws Exception{
		
		//以前的方式:
		/*
		User u = new User();
		u.age = 12; //set
		System.out.println(u.age); //get
		*/
		

		//获取类
		Class c = Class.forName("User");

		//获取id属性
		Field idF = c.getDeclaredField("id");

		//获取到某个特定的属性可以用来?set , get
		Object o = c.newInstance();
		
		//打破封装
		idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。

		//给o对象的id属性赋值"110"
		idF.set(o, "110"); //set

		//get
		System.out.println(idF.get(o));


	}
}

/*
	获取某个特定的方法,通过反射机制执行。

	以前:
	CustomerService cs = new CustomerService();
	boolean isSuccess = cs.login("admin","123");

	通过反射机制???

*/
import java.lang.reflect.*;

public class ReflectTest07
{
	public static void main(String[] args) throws Exception{
		
		//1.获取类
		Class c = Class.forName("CustomerService");


		//获取某个特定的方法
		//通过:方法名+形参列表
		Method m = c.getDeclaredMethod("login",String.class,String.class);

		//通过反射机制执行login方法.
		Object o = c.newInstance();
		
		//调用o对象的m方法,传递"admin""123"参数,方法的执行结果是retValue
		Object retValue = m.invoke(o, "admin","456");

		System.out.println(retValue); //true
		
	}
}

代理模式

代理: 就是让代理角色帮助真实角色完成一件事情;

静态代理

静态代理相当于是多写了一个代理类,在调用的时候调用的是代理类,在代理类中的处理还是原生的处理逻辑,不过在前后添加上需要添加的代码。
缺点:需要为每一个被代理的对象都创建一个代理类。

package 代理模式;

public interface GiveGift {
    void giveDolls();
    void giveFlowers();
    void giveChocolate();
}

package 代理模式;

public class Persuit implements GiveGift {

    SchoolGirl mm;

    public Persuit(SchoolGirl mm) {
        this.mm = mm;
    }

    @Override
    public void giveDolls() {
        System.out.println(mm.getName()+" 送你娃娃");
    }

    @Override
    public void giveFlowers() {
        System.out.println(mm.getName()+" 送你花花");
    }

    @Override
    public void giveChocolate() {
        System.out.println(mm.getName()+" 送你巧克力");
    }
}

package 代理模式;

public class Proxy implements GiveGift {
    Persuit gg;

    public Proxy(SchoolGirl mm) {
        gg = new Persuit(mm);
    }

    @Override
    public void giveDolls() {
        gg.giveDolls();
    }

    @Override
    public void giveFlowers() {
        gg.giveFlowers();
    }

    @Override
    public void giveChocolate() {
        gg.giveChocolate();
    }
}

package 代理模式;

public class SchoolGirl {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

package 代理模式;

public class Test {
    public static void main(String[] args) {
        SchoolGirl mm = new SchoolGirl();
        mm.setName("郝英");
        Proxy proxy = new Proxy(mm);
        proxy.giveDolls();
        proxy.giveFlowers();
        proxy.giveChocolate();
    }
}

动态代理

Java标准库提供了动态代理功能,允许在运行期动态创建一个接口的实例; 动态代理是通过 Proxy 创建代理对象,然后将接口方法“代理”给 InvocationHandler 完成的。以下例子代理类同时代理了两个接口;
代码中使用Rent proxy = (Rent) proxyHander.getProxy();或者Rent2 proxy = (Rent2) proxyHander.getProxy();来使用不同接口的方法;

package 代理模式.动态代理;

//出租房屋
public interface Rent {
    public void rent();
}

package 代理模式.动态代理;

public interface Rent2 {
    public void rent2();
}

package 代理模式.动态代理;

//房东要买房
public class Host implements Rent ,Rent2{

    public void rent(){
        System.out.println("出租房屋");
    }

    @Override
    public void rent2() {
        System.out.println("出租房屋2");
    }
}

package 代理模式.动态代理;

import com.sun.org.apache.xml.internal.resolver.readers.ExtendedXMLCatalogReader;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyHander  implements InvocationHandler {
    private Object target;

    public ProxyHander(Object target) {
        this.target = target;
    }

    //生成代理对象
    public Object getProxy(){
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        Object result = method.invoke(target, args);
        fare();
        return result;
    }

    public void seeHouse(){
        System.out.println("看房");
    }
    public void fare(){
        System.out.println("收取中介费");
    }
}

package 代理模式.动态代理;

public class Test {
    public static void main(String[] args) {
        Host host = new Host();
        ProxyHander proxyHander = new ProxyHander(host);
        Rent2 proxy = (Rent2) proxyHander.getProxy();
        proxy.rent2();

    }
}

在调用Proxy.newProxyInstance之前,加一句System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”);,就会在项目的根目录生成一个$Proxy0.class,本来这是字节码文件不能直接查看的,但IDEA会自动帮我们反编译class文件。注意以下代码中的: **super.h.invoke(this, m3, (Object[])null);**并不是反射调用因为h并不是Method对象,这里是调用InvocationHandler接口的实现类,也就是ProxyHander的invoke方法.
在这里插入图片描述

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.sun.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import 代理模式.动态代理.Rent;
import 代理模式.动态代理.Rent2;

public final class $Proxy0 extends Proxy implements Rent, Rent2 {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m4;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void rent() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void rent2() throws  {
        try {
            super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m3 = Class.forName("代理模式.动态代理.Rent").getMethod("rent");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m4 = Class.forName("代理模式.动态代理.Rent2").getMethod("rent2");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值