抽象類是無法實例化的,因此無法使用@Service等這種注解直接將抽象類交給ioc容器管理,但是項目中往往需要有很多子類公用抽象父類的模板方法,那么怎么實現呢?
錯誤演示
1、抽象類
@Component public abstract class BaseService { @Autowired Dao dao; }
2、子類
@Component public class MyService extends BaseService{ public void print(){ //運行時為null System.out.print(dao.toString()); } }
在我們實例化子類對象的時候,抽象父類不能實例化,因為spring注入的是實例對象,而不是類,所以spring不會將dao自動裝配注入到一個實例中。
解決方法
一、使用ApplicationContextAware
1、工程圖
jar包只需要引入spring-context即可。
2、ApplicationContextUtil
package spring.chapter1.utils; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class ApplicationContextUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ApplicationContextUtil.applicationContext = applicationContext; } public static Object getObject(String id) { Object object = null; object = applicationContext.getBean(id); return object; } public static ApplicationContext getSpringContext() { return applicationContext; } }
3、抽象類
package spring.chapter1.service; import spring.chapter1.dao.Dao; import spring.chapter1.utils.ApplicationContextUtil; public abstract class BaseService { Dao dao; public BaseService() { this.dao = (Dao) ApplicationContextUtil.getObject("dao"); } }
4、子類
package spring.chapter1.service; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; @Component /** * 因為BaseService中構造器需要使用applicationContextUtil這個bean,所以需要加@DependsOn這個注解。 *注解作用:1、保證applicationContextUtil總是在MyService之前實例化 * 2、保證applicationContextUtil總是在MyService銷毀之后銷毀 */ @DependsOn("applicationContextUtil") public class MyService extends BaseService{ public MyService() { super(); } public void print(){
dao.process();
}
}
5、Dao(一個demo組件,模擬調用某個bean的方法而已)
package spring.chapter1.dao;
import org.springframework.stereotype.Component;
@Component
public class Dao {
public void process() {
System.out.println("抽象父類中成功注入dao");
}
}
6、bean配置類(定義bean掃描策略)
package spring.chapter1.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(value = "spring.chapter1") public class BeanConfig { }
7、測試類
package spring.chapter1.main; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import spring.chapter1.config.BeanConfig; import spring.chapter1.service.MyService; public class SpringMain { @Test public void test() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class); MyService myService = (MyService) context.getBean("myService"); myService.print(); } }
運行結果:
二、子類bean為父類注入bean
1、抽象類
public abstract class BaseService { Dao dao; }
2、子類
@Component public class myService extends BaseService{ //Autowired修飾方法時,根據方法參數類型判斷實例化哪個類 @Autowired public void printDao(Dao dao){ super.dao = dao;//父類屬性注入 } public void print(){ System.out.print(dao.toString()); } }
通過這種方式,抽象類就可以獲取到bean,並進行使用了。