java反射学习
1)字节码文件的三种获取方式
①:Object类的getClass()方法:对象.getClass()
②:数据类型的静态的class属性:类名.class
③:通过Class类的静态方法forName(String className)(一般只用最后一种,前面两种了解即可)
2)反射获取类的构造方法
public Constructor<?>[] getConstructors():所有公共构造方法
public Constructor<?>[] getDeclaredConstructors():所有构造方法 包括私有
public Constructor<T> getConstructor(Class<?>... parameterTypes):获取单个构造方法
比如:
Class clazz = Class.forName("com.heima.bean.Person");
Constructor c = clazz.getConstructor(String.class,int.class); //获取有参构造
Person p = (Person) c.newInstance("张三",23); //通过有参构造创建对象
System.out.println(p);
3)反射获取类的成员变量
Field[] fields = c.getFields();// 获取所有公共的成员变量
Field[] fields = c.getDeclaredFields();// 获取所有的成员变量
Field field = c.getField("age");// 获取单个的成员变量
比如:
Class clazz = Class.forName("com.heima.bean.Person");
Constructor c = clazz.getConstructor(String.class,int.class); //获取有参构造
Person p = (Person) c.newInstance("张三",23); //通过有参构造创建对象 //修改姓名的值
Field f = clazz.getDeclaredField("name"); //暴力反射获取字段
f.setAccessible(true); //去除私有权限
f.set(p, "李四");
System.out.println(p);
4)反射获取类的成员方法
Method[] methods = c.getMethods();// 所有公共方法,包括父类的
Method[] methods = c.getDeclaredMethods();// 本类的所有方法
比如:
Class clazz = Class.forName("com.heima.bean.Person");
Constructor c = clazz.getConstructor(String.class,int.class); //获取有参构造
Person p = (Person) c.newInstance("张三",23); //通过有参构造创建对象
Method m = clazz.getMethod("eat"); //获取eat方法
m.invoke(p);
Method m2 = clazz.getMethod("eat", int.class); //获取有参的eat方法
m2.invoke(p, 10);
java动态代理学习
public interface Student { public void login(); public void submit(); } public class StudentImp implements Student { @Override public void login() { System.out.println("登录"); } @Override public void submit() { System.out.println("提交"); } } public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限校验"); method.invoke(target, args); //执行被代理target对象的方法 System.out.println("日志记录"); return null; } } StudentImp si = new StudentImp(); si.login(); si.submit(); System.out.println("-------------------------------"); MyInvocationHandler m = new MyInvocationHandler(si); Student s = (Student)Proxy.newProxyInstance(si.getClass().getClassLoader(), si.getClass().getInterfaces(), m); s.login(); s.submit();
/** * 一个演员 */ public class Actor{//没有实现任何接口 public void basicAct(float money){ System.out.println("拿到钱,开始基本的表演:"+money); } public void dangerAct(float money){ System.out.println("拿到钱,开始危险的表演:"+money); } } public class Client { /** * 基于子类的动态代理 * 要求: * 被代理对象不能是最终类 * 用到的类: * Enhancer * 用到的方法: * create(Class, Callback) * 方法的参数: * Class:被代理对象的字节码 * Callback:如何代理 * @param args */ public static void main(String[] args) { final Actor actor = new Actor(); Actor cglibActor = (Actor) Enhancer.create(actor.getClass(), new MethodInterceptor() { /** * 执行被代理对象的任何方法,都会经过该方法。在此方法内部就可以对被代理对象的任何方法进行增强。 * * 参数: * 前三个和基于接口的动态代理是一样的。 * MethodProxy:当前执行方法的代理对象。 * 返回值: * 当前执行方法的返回值 */ @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { String name = method.getName(); Float money = (Float) args[0]; Object rtValue = null; if("basicAct".equals(name)){ //基本演出 if(money > 2000){ rtValue = method.invoke(actor, money/2); } } if("dangerAct".equals(name)){ //危险演出 if(money > 5000){ rtValue = method.invoke(actor, money/2); } } return rtValue; } }); cglibActor.basicAct(10000); cglibActor.dangerAct(100000); } }