Spring IOC 經常使用技術總結

ApplicationContext

上下文,這是一個比BeanFactory功能更增強大的容器,可是具體ApplicationContext都有些什麼強大的功能呢?一塊兒來看看吧。java

clipboard.png

其實看ApplicationContext所繼承的接口,就能明白都有些什麼功能,這裏說一說我以爲比較重要的一個功能——ApplicationEventPublisher:程序事件發佈。spring

監聽容器啓動

通俗來講就是我這個容器運行時會發布一些事件,而後咱們能夠對這些容器發佈的事件進行監聽。ide

@Component
public class TestListener implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println("我是一個監聽程序啓動的方法");
    }
}

@ComponentScan("com.mengyunzhi.spring")
public class Application {

    public static void main(String []args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
    }
}

ApplicationListener,函數式接口,用於監聽某個繼承自ApplicationEvent類型的事件,當該事件發佈時,執行咱們實現的onApplicationEvent方法。函數

除了咱們使用的事件ContextRefreshedEvent容器初始化或刷新以外,還有ContextClosedEvent容器即將關閉,RequestHandledEvent 請求處理後發佈的事件。spa

clipboard.png

運行結果:code

clipboard.png

監聽器執行順序

能夠實現Spring提供的Ordered接口,實現其生命的getOrder方法,返回的值越小表示執行越靠前。xml

clipboard.png

@Component
public class TestListener implements ApplicationListener<ContextRefreshedEvent>, Ordered {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println("我是一個監聽程序啓動的方法");
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

@Component
public class NewListener implements ApplicationListener<ContextRefreshedEvent>, Ordered {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println("我是一個新的監聽方法");
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

運行結果:對象

clipboard.png

自動裝配

Autowired

熟悉不過的自動裝配,@Autowired註解的本質是根據Bean的類型進行裝配,就是舊版本Spring中的ByType方式。blog

@Autowired
private TestService testService;

聲明須要一個TestService類型的對象,而後Spring會在上下文中尋找符合條件的Bean,並未咱們注入進來。繼承

Qualifier

而若是一個接口有多個實現,在上下文中就會有多個符合該條件的Bean,因此咱們就須要對注入的Bean進行ByName聲明,根據Bean的名稱進行注入。使用註解@Qualifier進行根據名稱的裝配。

如今實現類上爲該組件聲明一個名稱,或者在xml配置中爲該Bean配置名稱。

@Service("TestServiceImpl")
public class TestServiceImpl implements TestService {

    @Override
    public void show() {
        System.out.println("我是TestServiceImpl, TestService的實現");
    }
}

@Service("NewTestServiceImpl")
public class NewTestServiceImpl implements TestService {

    @Override
    public void show() {
        System.out.println("我是NewTestServiceImpl, 也是TestService的實現");
    }
}

clipboard.png

運行結果:

clipboard.png

Primary

若是咱們一個接口有多個實現類,可是98%的業務環境下都須要注入咱們的NewTestServiceImpl實例,咱們不肯意寫那麼多的Qualifier,因此咱們能夠聲明某個類爲Primary而被優先注入。極少數狀況下須要別的實例的話再去Qualifier聲明。

@Primary
@Service("NewTestServiceImpl")
public class NewTestServiceImpl implements TestService {

    @Override
    public void show() {
        System.out.println("我是NewTestServiceImpl, 也是TestService的實現");
    }
}

運行結果:

clipboard.png

Bean的方法

某些業務環境,可能一個Bean在執行完構造函數以後還不能被使用,還須要執行一些初始化操做,畢竟優雅的代碼應該把對象的構造與初始化分開。

@Service
public class NewTestServiceImpl implements TestService {

    @PostConstruct
    public void init() {
        System.out.println("我是init方法,我初始化NewTestServiceImpl");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("我是destroy方法,我銷燬NewTestServiceImpl");
    }
}

使用@PostConstruct標註在對象創造以後執行的初始化操做,使用@PreDestroy標註在對象銷燬以前執行的銷燬邏輯。

ApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
((AnnotationConfigApplicationContext) context).close();

運行結果:

clipboard.png

相關文章
相關標籤/搜索