反射和代理

反射和代理

反射

反射:refecton,反射机制:在运行过程中,可以动态获取到类中的任意的属性和方法(类型,方法,构造器,注解),可以动态的去操作对象的属性和方法,实现各种操作

编写:java源文件—》编译成:.class文件—》jvm加载到内存中—》解释执行—》操作系统

通过加载到内存中的class类型是实例,获取到该实例所代表的类中的(属性对象,方法对象,构造方法,对象)

Preson—》子类对象–》子类对象(参数)
反射是框架的基础
获取class类型的实例
1.Class.forName(“完全限定的类名”)使用频率高;耦合度低
2.类名.class
3.对象.getClass();
加载到内存中的Class类型的实例是唯一的,单例

 public static void main(String[] args) {
        try {
            //获取Class类型的实例
            final Class<?> aClass = Class.forName("com.aaa.lang.Student");
            Class<Student> aClass1 = Student.class;

            Student student=new Student();
            Class<? extends Student> aClass2 = student.getClass();
            //==:引用数据类型:比较地址  是否一样
            System.out.println(aClass==aClass1);
            System.out.println(aClass1==aClass2);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

获取类中的字段

Field类型

 public static void main(String[] args) {

        Student student=new Student();
        try {
            //获取Class类型的实例
            Class<?> aClass = Class.forName("com.aaa.lang.Student");
            //获取到公有的字段
            Field[] fields = aClass.getFields();
//            System.out.println(fields.length);
            //获取类型中所有的字段
            Field[] fields1 = aClass.getDeclaredFields();
//            System.out.println(fields1.length);

            //获取到该Class实例所代表的类的一个实例
            Object object=aClass.newInstance();

            //根据名字获取某字段
            Field field = aClass.getDeclaredField("name");
            //去掉安全限制,允许访问私有字段
            field.setAccessible(true);
            //参数1改字段所属的对象,参数2:给字段设置的值
            field.set(student,"老胡");
            //获取该对象中的该字段的值
            System.out.println(field.get(student));
            System.out.println(fields.length);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

获取类中的方法

Method类型

 public static void main(String[] args) {

            try {
                Class<?> aClass = Class.forName("com.aaa.lang.Student");
                //
  //类型。。。参数名称:可变参数(变长参数),方法内部是一 数组的方式进行操作
                Method say= aClass.getMethod("say", String.class);
                //动态调用方法
                //aClass.newInstance():对象
                say.invoke(aClass.newInstance(),"老虎");
                test1("hello",say);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

    }
    public static void test1(String str,Method method){
//        method.invoke(,)
    }

获取类中的构造方法

Constructor类型

 public static void main(String[] args) {
        try {
            Class<?> aClass = Class.forName("com.aaa.lang.Student");
            Constructor<?> constructor = aClass.getConstructor(String.class, Integer.class);
            //创建对象
            Object object = constructor.newInstance("sdf", 20);
            Student student= (Student) object;

            System.out.println(student.getName());
            System.out.println(student.getAge());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }

综合案例

Spring框架:IOC;Spring容器去创建对象

配置文件

init.propreties

stu1=com.aaa.lang.Student
empDao=com.aaa.lang.EmpDaoImpl

测试:

 private static HashMap<String,Object> map=new HashMap<>();
    //读取配置文件
    public  static  void inti(){
        //属性对象
        Properties properties=new Properties();
        //获取当前类class的实例:getClassLoader()获取对应的类加载器
        InputStream stream = Spring.class.getResourceAsStream("init.properties");
        try {
            //加载数据流中的数据
            properties.load(stream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //获取到文件中的键值对集合
        Set<Map.Entry<Object, Object>> entries = properties.entrySet();
        //遍历set集合:迭代器
        Iterator<Map.Entry<Object,Object>> iterator=entries.iterator();
        while (iterator.hasNext()){
            //获取下一个元素:键值对的对象
            Map.Entry<Object,Object> entry=iterator.next();
            String key = entry.getKey().toString();
            String value=entry.getValue().toString();

//            System.out.println(key+":"+value);
            try {
                map.put(key, Class.forName(value).newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        //根据key获取对应的实例(对象)
        Object object = map.get("empDao"); 
        EmpDao dao= (EmpDao) object; 
        dao.show();
    }

java语言局别一定的动态特性,灵活性增强,效率低

综合案例:模拟实现了Spring里面的IOC功能

提前创建爱你乙烯类对象,用的时候直接拿出来用

1.提前去创建对象

2.对象创建的容器(模拟spring容器)

实现步骤

1.准备一个HashMap集合,通过key获取value(Object)

2.需要把要创建的对象记录到文件中:xml

key1=完全限定的类名(Class.forname("类名"))
key2=完全限定的类名(Class.forname("类名"))
key3=完全限定的类名(Class.forname("类名"))
key4=完全限定的类名(Class.forname("类名"))

3.读取属性文件

HashMap和Hashtable

HashMap单线程,线程不安全但速度快

Hashtable多线程,有同步锁线程安全,但速度慢

代理

代理:中间商

设计模式:

一种代理模式:

通过代理对象去访问目标对象,在不改变目标对象的原有的功能的基础之上,对目标对象进行增强 (扩展)目标对象的功能。

原则:

对扩展开放,对修改关闭。

代理分类

1、静态代理

2、动态代理

jdk动态代理

cglib动态代理

静态代理

通过代理方式,给Dao接口的实现类增加日志记录功能?

1、代理类实现目标接口

2、代理类中添加对目标对象的引用

3、测试

目标类和代理类都要实现目标接口

动态代理

jdk动态代理:要求目标对象必须实现指定的接口;

底层使用jdk动态生成目标接口的实现类的实例;动态生成class文件(内存)

cglib动态代理:直接对类进行代理;

动态生成了目标类的子类的代理对象;

如何往一个指定的类中传递参数?

1、将需要传递的参数定义成属性

2、通过构造方法实现对该属性的初始化

3、在类中使用该属性

jdk动态代理实现:

封装类用来生成代理对象

public class JDKProxy implements InvocationHandler {
//声明要代理的目标对象
    private Object target;
    //通过构造方法完成对目标对象的初始化
    public JDKProxy(Object target){
        this.target=target;
    }

    /**
     * 产生代理对象
     * @return
     */
    public Object createProxy(){
        //jdk动态生成一个代理对象
        //参数1classLoader loader 类加载器,获取目标类的类加载器
        //参数2 class<>[] interfaces目标类实现的一一列接口
        //参数2 InvocationHandler 对目标方法的拦截处理器,接口,实现该接口的一个对象
        Object proxy=(EmpDao) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
        return proxy;
    }

    /**
     *
     * @param proxy  代理对象
     * @param method  目标方法
     * @param args    目标方法中使用到的参数
     * @return    目标方法调用后返回的结果
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("扩展的功能");
        //调用目标方法返回结果
        Object object=method.invoke(target,args);
        return object;
//        return null;
    }
}

jdk动态代理实现

封装到一个类中,方法:产生代理对象

1.类JDKProxy2

2.目标对象被代理的对象

3.对目标方法进行扩展(实现InvocationHandle接口)

4.产生代理对象

Peoxy.newProxyInstance()

cglig动态代理

1.引入jar包

2.仿照jdk动态代理的过程

 private Object target;
    public CgProxy(Object target){
        this.target=target;
    }

    /**
     *
     * @param o   代理方法
     * @param method   目标方法对象
     * @param objects    目标方法参数
     * @param methodProxy  目标方法代理队形
     * @return       目标方法执行后的结果
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("扩展代码");
        Object result=methodProxy.invoke(target,objects);
        return result;
    }
    //代理对象
    public Object createPorxy(){
        //工具类:Enhancer
        Enhancer enhancer=new Enhancer();
        //设置超类
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        //生成代理对象
        Object o = enhancer.create();
        return o;
    }

测试

 public static void main(String[] args) {
        EmpService empService=new EmpService();

        CgProxy cgProxy=new CgProxy(empService);
        EmpService proxy= (EmpService) cgProxy.createPorxy();

        proxy.show();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值