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

相关文章
相关标签/搜索