1. 程式人生 > >徹底搞懂Spring類載入(註解方式)

徹底搞懂Spring類載入(註解方式)

目錄

通過 Spring 註冊的類一共只有三種載入方式!

環境:
spring-context 4.2.6
jdk 7
Eclipse Neon for j2ee

最簡單的配置

<?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"
xmlns:mvc="http://www.springframework.org/schema/mvc" 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.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd"
>
<!-- 掃描註解 --> <context:component-scan base-package="org.foo" /> </beans>

入口方法:

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringEntrance {
    public static void main(String[] args){
        ClassPathXmlApplicationContext resource = new
ClassPathXmlApplicationContext( new String[]{ "applicationContext.xml" }); } }

專案結構:

src
└── main
   └── java
      ├── applicationContext.xml
      └── org
          └── foo
              ├── service
              │   ├── TestDemo.java
              │   └── Test.java
              └── SpringEntrance.java

單例+預載入(預設)

//專案一啟動就產生一個且僅一個例項,即單例。
//並且,通過 @Autowired 只能獲得這個單例。new Test()則不受單例限制
@Component
public class Test{

}

單例+懶載入

//專案啟動時不載入
//僅當 TestDemo 類的 @Autowired Test 被掃描到時,才生成 Test 類的一個且僅一個例項。
//並且,通過 @Autowired 只能獲得這個單例。new Test()則不受單例限制
@Lazy
@Component
public class Test{

}

  正確的載入時機

package org.foo.service;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TestDemo {
//禁止使用 @Autowired 標籤載入 @Lazy 的類
//  @Autowired 
//  TestSingle testSingle;

    //通過 BeanFactory 介面建立例項
    @Autowired
    BeanFactory beanFactory;

    public void doSth(){
        //test 是 Test 類名首字母小寫!一定要首字母小寫!
        //只有執行到這裡 Test 類才被例項化,延遲載入成功
        TestSingle ts=(TestSingle) beanFactory.getBean("test");
    }
}

  錯誤的載入時機:

//懶載入無效
//專案啟動時 TestDemo 被載入時,掃描 @Autowired 標籤,生成 Test 的單例
@Component
public class TestDemo{
    @Autowired // 專案啟動時,這裡就會建立 Test 的單例,Test 類的懶載入無效
    Test test; 
}

多例+懶載入(僅支援懶載入)

定義

//每個 @Autowired 生成一個例項,可以有多個例項
@Scope("prototype")
//@Lazy //無論加不加 @Lazy,被 @Scope("prototype") 修飾的類都會 懶載入。
@Component
public class Test{

}

呼叫:

package org.foo.service;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TestDemo {
//禁止使用 @Autowired 標籤載入 @Lazy 的類
//  @Autowired 
//  TestSingle testSingle;

    //通過 BeanFactory 介面建立例項
    @Autowired
    BeanFactory beanFactory;

    public void doSth(){
        Test test = null;
        for(int i=0;i<10;i++) {
            //test 是 Test 類名首字母小寫!一定要首字母小寫!
            //只有執行到這裡 Test 類才被例項化,延遲載入成功
            test = (Test) beanFactory.getBean("test");
        }
    }
}

spring beanfactory類高階用法

  反射方式載入類

beanFactory.getBean(
            task.getHandler() + "UrlSpider", // 反射獲得子類
            AbstractUrlSpider.class ); // 返回父型別

需要注意的問題

建構函式裡不支援 @Autowired 的例項

package org.foo.service;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TestDemo {
    @Autowired
    BeanFactory beanFactory;

    public TestDemo (){
        beanFactory.getBean("test",Test.class);
    }
}