番外 01:Spring IoC 实现原理简析,Java的反射机制,通过类名创建对象

转载请注明来源 赖赖的博客

前景概要

01 走进Spring,Context、Bean和IoC 中,我们看到了强大的Spring通过ApplicationContext实现了bean工厂(也就是对象工厂),那究竟是怎么实现的呢,本次给大家写一个小Demo展现其原理;

Spring bean的调用方式和配置方式

(详情可以查看 01 走进Spring,Context、Bean和IoC 这一课程)此处仅贴出代码,如果已经看过 01 走进Spring,Context、Bean和IoC 这一课,可以直接跳过前景概要。

运行App.java输出结果如下

hello

App.java

package me.laiyijie.demo;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import me.laiyijie.demo.service.AccountService;

/**
 * Hello
 *
 */
public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("root-context.xml");

        AccountService accountService = context.getBean(AccountService.class);

        System.out.println(accountService.sayHello());

        context.close();
    }
}

root-context.xml




    


AccountService.java

package me.laiyijie.demo.service;

public class AccountService {

    public String sayHello() {

        return "hello";
    }
}

pom.xml代码如下


    4.0.0

    me.laiyijie
    demo
    0.0.1-SNAPSHOT
    jar

    

        
        
            org.springframework
            spring-context
            4.3.2.RELEASE
        

    

通过类名创建对象

问题引出和分析

在App.java中,调出AccountService用了两步:

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("root-context.xml");

AccountService accountService = context.getBean(AccountService.class);

而root-context.xml中配置AccountService实例只用了一行配置


那么问题来了,Spring是如何通过这一行配置文件来创建这个对象的呢?

此处配置文件只提供了一个类的全限定名me.laiyijie.demo.service.AccountService,那么问题就转化成:

如何通过类名创建对象

问题解决

要解决通过类名创建对象的问题就要引入Java的反射机制。

实例:通过类名创建对象

App.java
package me.laiyijie.demo;

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

import me.laiyijie.demo.service.AccountService;

public class App {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException,
            InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        Class clazz = classLoader.loadClass("me.laiyijie.demo.service.AccountService");

        Constructor constructor = clazz.getConstructor();

        AccountService accountService = (AccountService) constructor.newInstance();

        System.out.println(accountService.sayHello());
    }
}

没有用到 new AccountService 却成功创建了他的对象并调用其方法。

调用过程如下
  1. 通过Thread获取当前的类加载器(ClassLoader
  2. 通过ClassLoader获取me.laiyijie.demo.service.AccountService对应的Class对象
  3. 通过Class对象获取构造函数对应的Constructor的对象
  4. 通过Contructor对象创建AccountService对象
  5. 调用sayHello方法

hello

你可能感兴趣的:(SpringFrameWork)