转载请注明来源 赖赖的博客
前景概要
在 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
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
AccountService.java
package me.laiyijie.demo.service;
public class AccountService {
public String sayHello() {
return "hello";
}
}
pom.xml代码如下
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
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 却成功创建了他的对象并调用其方法。
调用过程如下
通过Thread获取当前的类加载器(ClassLoader)
通过ClassLoader获取me.laiyijie.demo.service.AccountService对应的Class对象
通过Class对象获取构造函数对应的Constructor的对象
通过Contructor对象创建AccountService对象
调用sayHello方法
hello