轉(zhuǎn)載請(qǐng)注明來源 賴賴的博客
前景概要
在 01 走進(jìn)Spring,Context佣蓉、Bean和IoC 中披摄,我們看到了強(qiáng)大的Spring通過ApplicationContext實(shí)現(xiàn)了bean工廠(也就是對(duì)象工廠),那究竟是怎么實(shí)現(xiàn)的呢勇凭,本次給大家寫一個(gè)小Demo展現(xiàn)其原理疚膊;
Spring bean的調(diào)用方式和配置方式
(詳情可以查看 01 走進(jìn)Spring,Context虾标、Bean和IoC 這一課程)此處僅貼出代碼寓盗,如果已經(jīng)看過 01 走進(jìn)Spring,Context璧函、Bean和IoC 這一課傀蚌,可以直接跳過前景概要。
運(yùn)行App.java輸出結(jié)果如下
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
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<bean class="me.laiyijie.demo.service.AccountService"></bean>
</beans>
AccountService.java
package me.laiyijie.demo.service;
public class AccountService {
public String sayHello() {
return "hello";
}
}
pom.xml代碼如下
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.laiyijie</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
</dependencies>
</project>
通過類名創(chuàng)建對(duì)象
問題引出和分析
在App.java中蘸吓,調(diào)出AccountService用了兩步:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("root-context.xml");
AccountService accountService = context.getBean(AccountService.class);
而root-context.xml中配置AccountService實(shí)例只用了一行配置
<bean class="me.laiyijie.demo.service.AccountService"></bean>
那么問題來了善炫,Spring是如何通過這一行配置文件來創(chuàng)建這個(gè)對(duì)象的呢?
此處配置文件只提供了一個(gè)類的全限定名me.laiyijie.demo.service.AccountService
,那么問題就轉(zhuǎn)化成:
如何通過類名創(chuàng)建對(duì)象
問題解決
要解決通過類名創(chuàng)建對(duì)象的問題就要引入Java的反射機(jī)制美澳。
實(shí)例:通過類名創(chuàng)建對(duì)象
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
卻成功創(chuàng)建了他的對(duì)象并調(diào)用其方法销部。
調(diào)用過程如下
- 通過Thread獲取當(dāng)前的類加載器(
ClassLoader
) - 通過
ClassLoader
獲取me.laiyijie.demo.service.AccountService
對(duì)應(yīng)的Class
對(duì)象 - 通過
Class
對(duì)象獲取構(gòu)造函數(shù)對(duì)應(yīng)的Constructor
的對(duì)象 - 通過
Contructor
對(duì)象創(chuàng)建AccountService
對(duì)象 - 調(diào)用
sayHello
方法
hello