19 反射,静态代理,动态代理

19 反射,静态代理,动态代理

反射

概述
  • Java反射机制是在运行状态中 , 对于任意一个类 , 都能够知道这个类的所有属性和方法
  • 对于任意一个对象 , 都能够调用它的任意一个方法和属性
  • 这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制

在这里插入图片描述

Person类

import java.io.Serializable;

public class Person implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String name = "小孔";
	int age = 22;
	public String sex = "女";
	
	public Person() {
	}

	private Person(String name) {
		this.name = name;
	}

	public Person(String name, int age, String sex) {
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
	}

	private int getAge() {
		return age;
	}

	private void setAge(int age) {
		this.age = age;
	}
	
	public void show() {
		System.out.println(name+"---"+age+"---"+sex);
	}
}
获取Class对象
import java.util.Arrays;

public class ClassDemo1 {
	public static void main(String[] args) throws Exception {
		Class<?> fn = Class.forName("com.doit.day21.Person");
		
		Class<?>[] ins = fn.getInterfaces();
		
		System.out.println(Arrays.toString(ins));
		
		Package p = fn.getPackage();
		
		System.out.println(p);
		
		String name = fn.getSimpleName();
		
		System.out.println(name);
		
		Class<?> sc = fn.getSuperclass();
		
		System.out.println(sc);
		
		Object obj = fn.newInstance();
		
		System.out.println(obj);
	}
}
获取构造方法
  • 默认无法访问私有构造方法 , 如果非要访问 , 需要暴力破解
public Constructor[] getConstructors		//获取所有用public修饰的构造方法

public Constructor getConstructor(Class...args)		//获取单个的用public修饰构造方法

public Consturctor[] getDeclaredConstructors()		//获取所有的构造方法

public Constructor getDeclaredConstructor(Class...args)		//获取单个构造方法
import java.lang.reflect.Constructor;

public class ClassDemo2 {
	public static void main(String[] args) throws Exception {
		//得到Class对象
		Class<?> clazz = Class.forName("com.doit.day21.Person");
		
		//获取构造方法
		Constructor<?>[] con = clazz.getConstructors();
		for (Constructor<?> c : con) {
			System.out.println(c);
		}
		
		System.out.println("=================");
		
		Constructor<?>[] dcs = clazz.getDeclaredConstructors();
		
		for (Constructor<?> c : dcs) {
			System.out.println(c);
		}
		
		System.out.println("===================");
		
		Constructor<?> cc1 = clazz.getConstructor(String.class,int.class,String.class);
	
		Object obj1 = cc1.newInstance("小王",21,"男");
		
		System.out.println(obj1);
		
		Constructor<?> cc2 = clazz.getConstructor();
		
		Object obj2 = cc2.newInstance();
		
		System.out.println(obj2);
		
		//暴力反射
		Constructor<?> cc3 = clazz.getDeclaredConstructor(String.class);
		
		cc3.setAccessible(true);
		
		Object obj3 = cc3.newInstance("大白");
		
		System.out.println(obj3);
	}
}
获取成员变量
Field[] fs 		getFields

field[] fs		getDeclaredFields

Field			getField

Field			getDeclaredField
import java.lang.reflect.Field;

public class ClassDemo3 {
	public static void main(String[] args) throws Exception {
		//得到Class对象
		Class<?> clazz = Class.forName("com.doit.day21.Person");
		
		//获取变量
		Field f = clazz.getField("sex");
		
		System.out.println(f);
		
		Object obj = clazz.newInstance();
		
		f.set(obj, "女");//对象.变量名=初始化值      变量的对象.set(对象,初始化值)
		
		System.out.println(obj);
		
		Field f2 = clazz.getDeclaredField("age");
		
		System.out.println(f2);
		
		f2.set(obj, 25);
		
		System.out.println(obj);
		
		Field f3 = clazz.getDeclaredField("name");
		
		f3.setAccessible(true);
		
		f3.set(obj, "小张");
		
		System.out.println(obj);
		
	}
}
获取成员方法
Method[]	getMethods

Method[]	getDeclaredMethods

Method		getMethod

Method		getDeclaredMethod
import java.lang.reflect.Method;

public class ClassDemo4 {
	public static void main(String[] args) throws Exception {
		//得到Class对象
		Class<?> clazz = Class.forName("com.doit.day21.Person");
		
		//获取成员方法
		Method method = clazz.getMethod("show");
		
		Object obj = clazz.newInstance();
		
		method.invoke(obj);
		
		System.out.println("=============================");
		
		Method dm = clazz.getDeclaredMethod("setAge", int.class);
	
		dm.setAccessible(true);
		
		dm.invoke(obj, 28);
		
		System.out.println(obj);
		
		System.out.println("==============================");
		
		Method d = clazz.getDeclaredMethod("getAge");
		
		d.setAccessible(true);
		
		Object i = d.invoke(obj);
		
		System.out.println(i);
		
	}
}
练习
ArrayList的一个对象,我想在这个集合中添加一个整型数据,如何实现呢?
import java.lang.reflect.Method;
import java.util.ArrayList;

public class ClassDemos {
	public static void main(String[] args) throws Exception {
		ArrayList<String> a = new ArrayList<String>();
		
		a.add("白茶清欢");
		a.add("无别事");
		a.add("我在等风");
		a.add("也等你");
		
		Class<? extends ArrayList> clazz = a.getClass();
		
		Method m = clazz.getMethod("add", Object.class);
		
		m.invoke(a,520);
		
		System.out.println(a);
	}
}
反射解耦合
public interface TeacherInterface {

	void teach();

}
public class OldTeacher implements TeacherInterface{

	@Override
	public void teach() {
		System.out.println("老老师个个都是老司机,车门焊的死死的");
	}
}
public class NewTeacher implements TeacherInterface{

	@Override
	public void teach() {
		System.out.println("新老师教学太死板,不会开车");
	}
}
import java.util.Properties;

public class TeacherTest {
	public static void main(String[] args) throws Exception {
		Properties pro = new Properties();
		
		pro.load(TeacherTest.class.getClassLoader().getResourceAsStream("config.properties"));
		
		String class_name = pro.getProperty("class_name");
		
		Class<?> fn = Class.forName(class_name);
		
		Object obj = fn.newInstance();
		
		TeacherInterface th = (TeacherInterface)obj;
		
		th.teach();
	}
}

代理

  • 需求 : 在原来方法的前后加入一些内容
静态代理
  • 通过proxy持有realObject的引用 , 并进行一层封装
接口
public interface UserInterface {
	 public  void login();
	 
	 public void register();
}
目标类
public class UserImpl implements UserInterface{

	@Override
	public void login() {
		System.out.println("登录成功");
	}

	@Override
	public void register() {
		System.out.println("注册成功");
	}	
}
代理类
public class UserProxy implements UserInterface{
	
	UserImpl user = new UserImpl();

	@Override
	public void login() {
		System.out.println("登录校验");
		
		user.login();
		
		System.out.println("用户信息保存");
	}

	@Override
	public void register() {
		System.out.println("注册成功");
	}
}
测试类
import java.util.Properties;

public class Test {
	public static void main(String[] args) throws Exception {
		Properties pro = new Properties();
		
		pro.load(Test.class.getClassLoader().getResourceAsStream("config.properties"));
		
		String name = pro.getProperty("proxy_name");
		
		Class<?> fn = Class.forName(name);
		
		Object obj = fn.newInstance();
		
		UserInterface user = (UserInterface)obj;
		
		user.login();
		
	}
}
动态代理
  • 使用Proxy调用newProxyInstance方法

    Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
    
    • 参数解释 :
      • ClassLoader : 传入一个类加载器 , 定义了由哪个ClassLoader对象来对生成的代理对象进行加载 ( 传入本类中的类加载器 )
      • Class<?>[] interfaces : 一组接口对象的数组 , 代表给接口中所有的方法都实现代理
      • InvocationHandler : 一个InvocationHandler对象 , 表示的是当我这个动态代理对象在调用方法的时候 , 会关联到哪一个InvocationHandler对象上
    • InvocationHandler中的方法 :
      • proxy : 真正的代理对象 , 不要使用
      • method : 指代的是我们所要调用真是对象的某个方法的Method对象 ; 使用代理对象调用哪个方法 , method就是哪个方法
      • args : 指代的是调用真实对象某个方法时接受的参数
接口
public interface UserInterface {
	 public  void login();
	 
	 public void register();
}
目标对象
public class UserImpl implements UserInterface{

	@Override
	public void login() {
		System.out.println("登录成功");
	}

	@Override
	public void register() {
		System.out.println("注册成功");
	}
}
生成代理对象
public class UserProxy implements UserInterface{
	
	UserImpl user = new UserImpl();

	@Override
	public void login() {
		System.out.println("登录校验");
		
		user.login();
		
		System.out.println("用户信息保存");
	}

	@Override
	public void register() {
		System.out.println("注册成功");
	}
}
测试类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyTest {
	public static void main(String[] args) {
		UserImpl user = new UserImpl();
		
		//第一个参数是要代理的对象的类加载器
		//第二个参数是要代理的对象的接口
		//第三个参数是一个匿名内部类  帮助我们完后真正的代理
		Object obj = Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {	
			
			//第一个参数 真正帮助我们完成代理的那个对象 不用管 由系统调用
			//第二个参数 是我们要代理哪个方法 这个method就代表哪个方法
			//第三个参数 你的方法中的参数列表
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				
				Object obj = null;
				if (method.getName().equals("login")) {
					System.out.println("登录校验");
					
					 obj = method.invoke(user);
					 
					 System.out.println("用户信息保存");
				}else {
					 obj = method.invoke(user);
				}
				return obj;
			}
		});
		
		UserInterface u = (UserInterface)obj;
		u.login();
		u.register();
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
动态代理是指在运行时动态生成代理类,而不需要事先编写代理类的代码。Java中的动态代理主要是通过Java.lang.reflect.Proxy类实现的。 下面是一个简单的动态代理示例,用于打印方法调用前后的时间戳: ```java import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Date; public class DynamicProxyDemo { public static void main(String[] args) { // 创建被代理对象 HelloServiceImpl helloService = new HelloServiceImpl(); // 创建代理对象 HelloService proxy = (HelloService) Proxy.newProxyInstance( helloService.getClass().getClassLoader(), helloService.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 打印时间戳 System.out.println(new Date() + " " + method.getName() + "() start"); // 调用被代理对象的方法 Object result = method.invoke(helloService, args); // 打印时间戳 System.out.println(new Date() + " " + method.getName() + "() end"); return result; } }); // 调用代理对象的方法 proxy.sayHello("World"); } } interface HelloService { void sayHello(String name); } class HelloServiceImpl implements HelloService { @Override public void sayHello(String name) { System.out.println("Hello, " + name + "!"); } } ``` 在上面的示例中,我们创建了一个HelloServiceImpl的实例作为被代理对象,然后通过Proxy.newProxyInstance方法创建了一个代理对象,同时指定了代理对象的处理器InvocationHandler。在InvocationHandler中,我们实现了代理对象方法的调用,包括方法调用前后的时间戳打印。最后,我们通过代理对象调用了HelloService接口中的sayHello方法,实际上调用的是被代理对象HelloServiceImpl中的sayHello方法,同时在方法调用前后打印了时间戳。 运行上面的代码,输出如下: ``` Wed Jun 30 19:07:37 CST 2021 sayHello() start Hello, World! Wed Jun 30 19:07:37 CST 2021 sayHello() end ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值