Spring Ioc基于java反射而远远高于反射---Spring框架三大核心接口

关于最基础的Ioc的概念及其思想,我们在

Spring核心功能–Ioc一节中都有过详细的讨论,这里就不多言了!

1、java反射

    那么,接下来,我们从反射入手,开始Spring征程。看例子:
package com.smart.reflect;

public class Car {
    private String brand;
    private String color;
    private int maxSpeed;

    public Car() {
    }

    public Car(String brand, String color, int maxSpeed) {
        this.brand = brand;
        this.color = color;
        this.maxSpeed = maxSpeed;
    }

    public void introduce() {
        System.out.println("brand:"+brand+";color:"+color+";maxSpeed:"+maxSpeed);
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getMaxSpeed() {
        return maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
        this.maxSpeed = maxSpeed;
    }
}
一般情况下,我们使用如下代码示例Car:
Car car = new Car();
car.setBrand("法拉利");

或者

Car car =  new Car("法拉利", "红色", 250);
以上两种方法都是采用传统的方式,直接调用目标类的方法。下面我们通过反射机制一一种间接的方式操控目标类:
package com.smart.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectTest {
    public static Car initByDefaultConst()
            throws ClassNotFoundException,
                    NoSuchMethodException,
                    IllegalAccessException,
                    InvocationTargetException,
                    InstantiationException {
        //①通过类加载器获取Car对象
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        Class clazz = classLoader.loadClass("com.smart.reflect.Car");
        /*
        * 也可以通过Class.forName();来获取Car对象
        */
        //②获取类的默认构造器对象并通过他实例化Car
        Constructor cons = clazz.getDeclaredConstructor((Class[]) null);
        Car car = (Car) cons.newInstance();

        //③通过反射方法设置属性
        Method setBrand = clazz.getMethod("setBrand", String.class);
        setBrand.invoke(car, "法拉利");
        Method setColor = clazz.getMethod("setColor", String.class);
        setColor.invoke(car, "红色");
        Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class);
        setMaxSpeed.invoke(car, 250);
        return car;
    }

    public static void main(String[] args)
            throws ClassNotFoundException,
            NoSuchMethodException,
            InvocationTargetException,
            InstantiationException,
            IllegalAccessException {
        Car car = initByDefaultConst();
        car.introduce();
    }
}

运行上述程序:
brand:法拉利;color:红色;maxSpeed:250
这些都是基础的反射的知识,我们就不详细给大家说明了。
关于类加载器,类加载机制,详见
java类加载
这里我们补充一些ClassLoad的知识。在java中ClassLoad是一个抽象类,位于java.lang包中,下面对该类的一些方法进行分析:

  • Class loadClass(String name):name参数指定类装载器需要装载的类的名字,必须使用全限定名,如 com.smart.reflect.Car。该方法有一个重载方法loadClass(String name, boolean resolve),resolve参数告诉类装载器是否需要解析该类。在初始化类之前,应考虑进行类解析工作,但并不是所有的类都需要解析。如果JVM只需要知道该类是否存在或找出该类的超类,那么就不需要进行解析。
  • Class defineClass(String name, byte[] b, int off, int len):将类文件的字节数组转换成JVM内部的java.lang.Class对象。字节数组可以从本地文件系统、远程网络获取。参数name为字节数组的全限定类名。
  • Class findSystemClass(String name):调用该方法来查看ClassLoader是否已装入某个类。如果已经装入,那么返回java.lang.Class对象;否则,抛出ClassNotFoundException异常。该方法是JVM默认使用的装载机制。
  • ClassLoader getParent():获取类装载器的父装载器。除根装载器外,所有的类装载器都有且只有一个父类装载器。ExtClassLoader的父装载器是根装载器,因为根装载器是非java语言写的,所以无法获得, 返回null;

    除了JVM默认的三个类加载器外,用户可以自己编写自己的第三方类加载器,以实现一些特殊的要求。类文件被装载并解析后,在JVM内拥有一个对应的java.lang.Class类描述对象,该类的实例都拥有指向这个类描述对象的引用,而类描述对象用拥有指向关联ClassLoader的引用
    

    这里写图片描述

反射机制

class反射对象描述类语义结构,可以从Class对象中获取构造函数,成员变量,方法类等元素的反射对象,并以编程的方式通过这些反射对象对目标类进行操作。
除了我们经常使用的Constructor类的构造函数反射类、Method类的方法反射类、Filed类的成员变量反射类之外,java还为包提供了Package反射类,在java5.0中还为注解提供了AnnotatedElement反射类。总之,java的反射体系保证了可以通过程序化的方式访问目标类中的所有元素,对于private和protected成员变量和方法,只要JVM的安全机制允许,也可以通过反射进行调用。具体就不演示了。

2、资源访问利器

负责任的说,这块是重点内容。

2.1、资源抽象接口
JDK所提供的访问资源的类(java.net.URL、File等)并不能很好的满足各种底层资源的访问需求,比如缺少从类路径(classpath:com.smart)或者Web容器的上下文(ServletContexst)中获取资源的类。鉴于此,Spring设计了一个Resource接口,他为应用提供了更强的底层资源访问能力。该接口拥有对应不容资源的实现类。先来了解一下Resource接口的主要方法。

  • boolena exists():资源是否存在。
  • boolean isOpen():资源是否已经打开。
  • URL getURL() throws IoException:如果底层资源可以表示成URL,则方法返回对应的URL对象。
  • File getFile() throws IoException:如果底层资源对应一个文件,则返回该方法的对应的File对象。
  • InputStream getInputStream() throws IoException:放回资源对应的输入流。
    Resource在Spring框架中起着不可获取的作用,Spring框架使用Resource装载各种资源,包括配置文件资源,国际化属性文件资源等。
    假如有一个文件位于Web应用的类路径下,用户可以通过以下方式对这个文件资源进行访问:

  • 通过FileSystemResource以文件系统绝对路径的方式进行访问。

  • 通过ClassPathResource以类路径的方式进行访问。
  • 通过ServletContextResource以相对于web应用根目录的方式进行访问。

相比于通过JDK的File类访问文件资源的方式,Spring的Resource实现类无疑提供了更加灵活便捷的访问方式,用户可以根据实际情况选择适合的Resource实现类访问资源。下面通过FileSystemResource 和ClassPathResource访问同一个资源。

package com.smart.resource;

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.PathResource
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值