抽象类是无法实例化的,因此无法使用@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,并进行使用了。