Bean對象的延遲加載(延遲建立)java
ApplicationContext 容器的默認⾏爲是在啓動服務器時將全部 singleton bean 提早進⾏實例化。提早實例化意味着做爲初始化過程的⼀部分,ApplicationContext實例會建立並配置全部的singleton bean。spring
lazy-init="" 配置bean對象的延遲加載 ,true或者false false就是當即加載緩存
<bean id="lazyResult" class="com.lagou.edu.pojo.Result" lazy-init="false"></bean>
咱們先來看一下當lazy-init="false"
也就是當即加載的時候:服務器
能夠看到,在容器啓動後,getBean以前,lazyResult這個bean已經存在了。app
而後咱們把lazy-init="true"
,設置爲true
框架
而後咱們F8往下走一步:
ide
發現出現了lazyResultpost
@Lazy:
性能
在bean的根標籤中:
測試
(1)開啓延遲加載⼀定程度提⾼容器啓動和運轉性能
(2)對於不常使⽤的 Bean 設置延遲加載,這樣偶爾使⽤的時候再加載,沒必要要從⼀開始該 Bean 就佔⽤資源
容器的頂級接口,定義了容器的一些基礎行爲,負責生產和管理Bean的一個工廠,具體使用它下面的子接口類型,好比ApplicationContext
spring中的bean有兩種
Bean建立的三種⽅式中的靜態⽅法和實例化⽅法和FactoryBean做⽤相似,FactoryBean使⽤較多,尤爲在Spring框架⼀些組件中會使⽤,還有其餘框架和Spring框架整合時使⽤
//可讓咱們自定義Bean的建立過程,完成複雜bean定義 public interface FactoryBean<T> { //返回FactoryBean建立的實例,若是isSingleton返回true,則該實例會放到Spring容器的單例緩存池中Map @Nullable T getObject() throws Exception; //返回FactoryBean建立的bean類型 @Nullable Class<?> getObjectType(); //返回做用域是否單例 default boolean isSingleton() { return true; } }
public class CompanyFactoryBean implements FactoryBean<Company> { private String companyInfo;//注入公司名稱,地址,規模 以逗號分隔 public void setCompanyInfo(String companyInfo) { this.companyInfo = companyInfo; } @Override public Company getObject() throws Exception { //建立複雜對象Company Company company=new Company(); String[] split = companyInfo.split(","); company.setName(split[0]); company.setAddress(split[1]); company.setScale(Integer.parseInt(split[2])); return company; } @Override public Class<?> getObjectType() { //返回bean的類型 return Company.class; } @Override public boolean isSingleton() { //是不是單例 return true; } }
public class Company { private String name; private String address; private int scale; //省略getset 和toString }
<bean id="companyBean" class="com.lagou.edu.factory.CompanyFactoryBean"> <property name="companyInfo" value="拉鉤,中關村,500"></property> </bean>
@org.junit.Test public void test(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); Object companyBean = applicationContext.getBean("companyBean"); System.out.println(companyBean); } //結果返回的是 Company{name='拉鉤', address='中關村', scale=500}
雖然在xml配置文件中配置的bean的class="com.lagou.edu.factory.CompanyFactoryBean"
可是返回的Company類型。
如何返回CompanyFactoryBean類型呢?
打印結果爲:com.lagou.edu.factory.CompanyFactoryBean@545b995e
Spring提供了兩種後處理bean的擴展接⼝,分別爲 BeanPostProcessor
和BeanFactoryPostProcessor
,二者在使⽤上是有所區別的。
⼯⼚初始化(BeanFactory)—> Bean對象
在BeanFactory初始化以後可使⽤BeanFactoryPostProcessor進⾏後置處理作⼀些事情
在Bean對象實例化(並非Bean的整個⽣命週期完成)以後可使⽤BeanPostProcessor進⾏後置處理作⼀些事情
注意:對象不⼀定是springbean,⽽springbean⼀定是個對象
按照上述描述的打印一下。看看是否一致:
//實現了BeanNameAware、BeanFactoryAware、ApplicationContextAware、InitializingBean,DisposableBean接口 public class Result implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean { private String status; private String message; //省略getset toString方法 @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("4.BeanFactoryAware:"+beanFactory); } @Override public void setBeanName(String name) { System.out.println("3.BeanNameAware:"+name); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("5.ApplicationContextAware:"+applicationContext); } @Override public void afterPropertiesSet() throws Exception { System.out.println("7.InitializingBean"); } public void initMethodTest(){ System.out.println("8.initMethod"); } @PostConstruct public void postCoustrcut(){ System.out.println("postCoustrcut"); } //銷燬以前執行 @PreDestroy public void preDestroy(){ System.out.println("銷燬以前執行"); } @Override public void destroy() throws Exception { System.out.println("DisposableBean"); } }
/** 攔截實例化以後的對象(實例化了 而且屬性注入了) 攔截全部的 */ @Component public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if ("lazyResult".equalsIgnoreCase(beanName)){ System.out.println("MyBeanPostProcessor before"); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if ("lazyResult".equalsIgnoreCase(beanName)){ System.out.println("MyBeanPostProcessor After"); } return bean; } }
//XML配置文件中: <bean id="lazyResult" class="com.lagou.edu.pojo.Result" init-method="initMethodTest"></bean>
//測試: @org.junit.Test public void testBeanLazy(){ ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); Object lazyResult = applicationContext.getBean("lazyResult"); System.out.println(lazyResult); applicationContext.close(); }
打印出: