spring_annotation_day_10

Spring注解开发

今天来学习,自定义组件想要使用Spring容器底层的一些组件来开发(ApplicationContext,BeanFactory,xxx)

自定义组件实现xxxAware,在创建对象的时候,会调用接口规定的方法注入相关组件,Aware会把Spring底层的一些组件注入到自定义的Bean中。

xxxAware:功能使用xxxAwareProcessor现实的,比如:ApplicationContextAware是用ApplicationContextAwareProcessor注入的。

ApplicationContextAware

1)在com.liuzhuo.bean包,随便找个Bean来实验:

这里使用Red类来实验:

@Component
public class Red implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("容器:" + applicationContext.toString());
    }
}

2)将Red类注入到容器中,使用包扫描,修改MainConfigOfAutowired配置类:
加入了com.liuzhuo.bean包的扫描

@Configuration
@ComponentScan(value = {"com.liuzhuo.controller", "com.liuzhuo.service", "com.liuzhuo.dao","com.liuzhuo.bean"})
public class MainConfigOfAutowired

3) 运行测试类IocTest_Autowired:

public class IocTest_Autowired {

    @Test
    public void test01() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);
        applicationContext.close();
    }
}

4) 运行结果:

org.springframework.context.event.internalEventListenerProcessor------postProcessBeforeInitialization
org.springframework.context.event.internalEventListenerProcessor------postProcessAfterInitialization
org.springframework.context.event.internalEventListenerFactory------postProcessBeforeInitialization
org.springframework.context.event.internalEventListenerFactory------postProcessAfterInitialization
mainConfigOfAutowired------postProcessBeforeInitialization
mainConfigOfAutowired------postProcessAfterInitialization
bookController------postProcessBeforeInitialization
bookController------postProcessAfterInitialization
bookDao2------postProcessBeforeInitialization
bookDao2------postProcessAfterInitialization
bookService------postProcessBeforeInitialization
bookService------postProcessAfterInitialization
bookDao------postProcessBeforeInitialization
bookDao------postProcessAfterInitialization
Cat constructer ···
cat------postProcessBeforeInitialization
Cat afterPropertiesSet ····
cat------postProcessAfterInitialization
Dog construct ····
dog------postProcessBeforeInitialization
Dog @PostConstruct ····
dog------postProcessAfterInitialization
容器:org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf: startup date [Wed Oct 17 14:08:27 CST 2018]; root of context hierarchy
red------postProcessBeforeInitialization
red------postProcessAfterInitialization
Dog @PreDestroy ····
Cat destroy ····
十月 17, 2018 2:08:28 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf: startup date [Wed Oct 17 14:08:27 CST 2018]; root of context hierarchy

Process finished with exit code 0

能观察到:

容器:org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf: startup date [Wed Oct 17 14:08:27 CST 2018]; root of context hierarchy

说明在Red类中,注入了容器类。

5)验证是否是同一个容器,修改测试方法:

public class IocTest_Autowired {

    @Test
    public void test01() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);
        System.out.println(applicationContext);
        applicationContext.close();
    }
}

6) 运行测试方法:

org.springframework.context.event.internalEventListenerProcessor------postProcessBeforeInitialization
org.springframework.context.event.internalEventListenerProcessor------postProcessAfterInitialization
org.springframework.context.event.internalEventListenerFactory------postProcessBeforeInitialization
org.springframework.context.event.internalEventListenerFactory------postProcessAfterInitialization
mainConfigOfAutowired------postProcessBeforeInitialization
mainConfigOfAutowired------postProcessAfterInitialization
bookController------postProcessBeforeInitialization
bookController------postProcessAfterInitialization
bookDao2------postProcessBeforeInitialization
bookDao2------postProcessAfterInitialization
bookService------postProcessBeforeInitialization
bookService------postProcessAfterInitialization
bookDao------postProcessBeforeInitialization
bookDao------postProcessAfterInitialization
Cat constructer ···
cat------postProcessBeforeInitialization
Cat afterPropertiesSet ····
cat------postProcessAfterInitialization
Dog construct ····
dog------postProcessBeforeInitialization
Dog @PostConstruct ····
dog------postProcessAfterInitialization
容器:org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf: startup date [Wed Oct 17 14:14:10 CST 2018]; root of context hierarchy
red------postProcessBeforeInitialization
red------postProcessAfterInitialization
十月 17, 2018 2:14:11 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf: startup date [Wed Oct 17 14:14:10 CST 2018]; root of context hierarchy
org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf: startup date [Wed Oct 17 14:14:10 CST 2018]; root of context hierarchy
Dog @PreDestroy ····
Cat destroy ····

Process finished with exit code 0

观察到:
容器:

org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf:

org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf:

一样,都是@2f410acf,说明是一个容器。


BeanNameAware

给自定义组件,注入自己在容器的id名。

1)修改Red类:

@Component
public class Red implements ApplicationContextAware,BeanNameAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("容器:" + applicationContext.toString());
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("自定义组件的id名字:"+name);
    }
}

2) 运行测试方法:

自定义组件的id名字:red
容器:org.springframework.context.annotation.AnnotationConfigApplicationContext@2f410acf: startup date [Wed Oct 17 14:21:56 CST 2018]; root of context hierarchy
red------postProcessBeforeInitialization
red------postProcessAfterInitialization

总结:

想让自定义组件使用Spring底层的组件,就实现xxxAware接口就行。

ApplicationContextAware
ApplicationEventPublisherAware
BeanClassLoaderAware
BeanFactoryAware
BeanNameAware
BootstrapContextAware
EmbeddedValueResolverAware
EnvironmentAware
ImportAware
LoadTimeWeaverAware
MessageSourceAware
NotificationPublisherAware
PortletConfigAware
PortletContextAware
ResourceLoaderAware
SchedulerContextAware
ServletConfigAware
ServletContextAware


原理:

1)在Red类下的setApplicationContext方法上面打上断点

2) 运行测试方法:

发现ApplicationContextAware是由ApplicationContextAwareProcessor处理的:

 @Override
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;

        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareInterfaces(bean);
                    return null;
                }
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

内部执行postProcessBeforeInitialization方法来判断自定义的组件是否实现类xxxAware接口。

最后调用invokeAwareInterfaces(bean)方法

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

调用相应的方法来实现注入。


  目录