Spring默認爲非懶加載(即在項目啓動時——Spring容器初始化過程中加載)
Spring設置爲非懶加載時,項目(Spring容器:ApplicationContext)啓動時立刻初始化,Spring容器會把所有的掃描包下的帶Spring註解(@Component、@Repository、@Service、@Controller)或者通過Spring xml配置的bean全都初始化。Spring容器初始化時,會調用默認構造方法,如果類中沒有默認的無參構造方法,那麼Spring初始化時會報錯誤。
以下兩點需要同學們注意:
- 由於在controller中會注入service層的類,由於,controller層面上的spring-mvc不是懶加載,即當在controller中注入service時,就會初始化此service類。因此即調用到誰初始化誰。
- 如果一個單例bean被設置爲懶加載,而另一個非懶加載的單例bean依賴於它,那麼當ApplicationContext提前實例化單例bean時,它必須也確保所有上述bean也被預先初始化,當然也包括設置爲懶加載的bean,即被非懶加載的bean依賴時懶加載的bean也會被初始化。
Spring懶加載配置方式:
- lazy-init=“true”:懶加載
- lazy-init=“false”:非懶載
- lazy-init=“default”:懶加載
示例代碼如下:
<bean id="test1" class="cn.java.ioc1.YelloMouseWolf" lazy-init="default"></bean>
懶加載與非懶加載的優缺點如下
懶加載:
優點:對象使用的時候纔去創建,節省資源。
缺點:不利於提前發現錯誤。
非懶加載:
優點:利於提前發現錯誤。
缺點:容器啓動的時候立刻創建對象。消耗資源。
當scope=“prototype” (多例——原型)時,默認以懶加載的方式產生對象。
當scope=“singleton” (單例)時,默認以非懶加載的方式產生對象。Spring的Scope(作用域)默認爲Singleton(單例)。
注:當Singeton的bean當中引用了一個ProtoType的bean時,由於Singleton的bean只會初始化一次,所以作用域爲ProtoType的bean不會被重新初始化,永遠會是同一個bean。Spring提供的解決方法可參考如下代碼
方法一:實現Spring的ApplicationContextAware接口
package com.tyyd.ioc.autowire.dao.impl;
import com.tyyd.ioc.autowire.dao.PigDao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
@Repository
@Scope("prototype")
public class PigDaoImpl implements PigDao {
public void test() {
System.out.println("PigDao");
}
}
package com.tyyd.ioc.autowire.service.impl;
import com.tyyd.ioc.autowire.dao.PigDao;
import com.tyyd.ioc.autowire.service.PigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PigServiceImpl implements PigService, ApplicationContextAware {
private ApplicationContext applicationContext;
@Autowired
private PigDao pigDao;
public void test() {
System.out.println("PigServiceImpl: " + this.hashCode());
System.out.println("PigDaoImpl: " + applicationContext.getBean("pigDaoImpl").hashCode());
}
public void setPigDao(PigDao pigDao) {
this.pigDao = pigDao;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
package com.tyyd.ioc.test;
import com.tyyd.ioc.autowire.config.JavaConfig;
import com.tyyd.ioc.autowire.service.impl.PigServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
PigServiceImpl pigService = (PigServiceImpl)annotationConfigApplicationContext.getBean("pigServiceImpl");
pigService.test();
}
}
方法二:通過註解@Lookup實現(相同代碼不做重複展示)
package com.tyyd.ioc.autowire.service.impl;
import com.tyyd.ioc.autowire.dao.PigDao;
import com.tyyd.ioc.autowire.service.PigService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
@Service
public class PigServiceImpl implements PigService {
public void test() {
System.out.println("PigServiceImpl: " + this.hashCode());
System.out.println("PigDaoImpl: " + getPigDao().hashCode());
}
@Lookup
public PigDao getPigDao() {
return null;
}
}
方法三:同樣通過註解@Lookup
package com.tyyd.ioc.autowire.service.impl;
import com.tyyd.ioc.autowire.dao.PigDao;
import com.tyyd.ioc.autowire.service.PigService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
@Service
public abstract class PigServiceImpl implements PigService {
public void test() {
System.out.println("PigServiceImpl: " + this.hashCode());
System.out.println("PigDaoImpl: " + getPigDao().hashCode());
}
@Lookup
public abstract PigDao getPigDao();
}