如何在抽象類中注入bean


抽象類是無法實例化的,因此無法使用@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,並進行使用了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM