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();
}
}