CodeZLei

  博客园 :: 首页 :: 博问 :: 闪存 :: :: 联系 :: 订阅 订阅 :: 管理 ::

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();
使用jdk实现,需要有接口,是接口的实现类
/**
 * 一个演员
*/
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);
    }
}
使用cglib实现,不需要接口是增强类的子类

 

 

posted on 2018-05-22 10:20  CodeZLei  阅读(152)  评论(0编辑  收藏  举报