A ApplicationContextAware

When a class implements the interface (ApplicationContextAware), it can easily get all the beans in the ApplicationContext. In other words, this class directly fetches all referenced bean objects in the Spring configuration file.

If you read the source code, you’ll see that BeanFactory actually holds properties in the Spring Bean container, but BeanFactory is an interface and is not exposed. What is really exposed is the ApplicationContext, Should be one of the ApplicationContext getAutowireCapableBeanFactory method, return AutowireCapableBeanFactory interface, Inherited the BeanFactory interface and AutowireCapableBeanFactory interface.

@Service
public class ExcelOutYardManager implements ApplicationContextAware {

    Map<String,IExcelOutYard> excelOutYardMap;

    private Map<String, IExcelOutYard> getExcelOutYard() {
        if (excelOutYardMap == null) {
            excelOutYardMap = new HashMap<String, IExcelOutYard>();
        }
        return excelOutYardMap;
    }

    public IExcelOutYard getImpleService(String messageType){
        return excelOutYardMap.get(messageType);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, IExcelOutYard> beansOfType = applicationContext.getBeansOfType(IExcelOutYard.class);
        this.getExcelOutYard();
        for (IExcelOutYard iExcelOutYard:beansOfType.values()) {
            excelOutYardMap.put(iExcelOutYard.messageType(),iExcelOutYard);
        }
    }
}
Copy the code

Two InitializingBean interface

The InitializingBean interface provides a way for beans to initialize methods, including only afterPropertiesSet methods, which classes that inherit this interface execute when initializing beans. You typically use this interface to do some initialization after Spring initializes a bean.

This feature is mostly used to set up automatic execution methods when the application is started, for example, when the application is started, the data is queried from the database and put into the object

@Service
public class EdiInitializingService implements InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
    -----
Copy the code

Three BeanPostProcessor interface

Some special processing logic is added before and after bean instantiation, configuration, and other initialization methods are completed in the Spring container. You need to define one or more BeanPostProcessor interface implementation classes and then register them with the Spring IOC container.

The following example intercepts the interface implementation class to be injected according to the custom annotation, using Java reflection and proxy knowledge to implement effective class injection.

public interface HelloService {
    public void sayHello();
}
Copy the code
@Service public class HelloServiceImpl1 implements HelloService{ @Override public void sayHello() { System.out.println(" HelloServiceImpl1"); }}Copy the code
@Service public class HelloServiceImpl2 implements HelloService{ @Override public void sayHello() { System.out.println(" HelloServiceImpl2"); }}Copy the code
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface RountingInjected {
    String value() default "helloServiceImpl1";
}
Copy the code
@Component public class HelloServiceInjectProcessor implements BeanPostProcessor { @Autowired private ApplicationContext  applicationContext; @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { Class<? > targetCls = bean.getClass(); Field[] targetFld = targetCls.getDeclaredFields(); For (Field Field: targetFld) {/ / find goals annotation class if (Field. IsAnnotationPresent (RountingInjected. Class)) {if (! field.getType().isInterface()) { throw new BeanCreationException("RoutingInjected field must be declared as an interface:" + field.getName() + " @Class " + targetCls.getName()); } try { this.handleRoutingInjected(field, bean, field.getType()); } catch (IllegalAccessException e) { e.printStackTrace(); } } } return bean; } /** * @param field * @param bean * @param type * @throws IllegalAccessException */ private void handleRoutingInjected(Field field, Object bean, Class type) throws IllegalAccessException { Map<String, Object> candidates = this.applicationContext.getBeansOfType(type); field.setAccessible(true); if (candidates.size() == 1) { field.set(bean, candidates.values().iterator().next()); } else if (candidates.size() == 2) { String injectVal = field.getAnnotation(RountingInjected.class).value(); Object proxy = RoutingBeanProxyFactory.createProxy(injectVal, type, candidates); field.set(bean, proxy); } else { throw new IllegalArgumentException("Find more than 2 beans for type: " + type); }}}Copy the code
public class RoutingBeanProxyFactory { private final static String DEFAULT_BEAN_NAME = "helloServiceImpl1"; public static Object createProxy(String name, Class type, Map<String, Object> candidates) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setInterfaces(type); proxyFactory.addAdvice(new VersionRoutingMethodInterceptor(name, candidates)); return proxyFactory.getProxy(); } static class VersionRoutingMethodInterceptor implements MethodInterceptor { private Object targetObject; public VersionRoutingMethodInterceptor(String name, Map<String, Object> beans) { this.targetObject = beans.get(name); if (this.targetObject == null) { this.targetObject = beans.get(DEFAULT_BEAN_NAME); } } @Override public Object invoke(MethodInvocation invocation) throws Throwable { return invocation.getMethod().invoke(this.targetObject, invocation.getArguments()); }}}Copy the code
@Component public class HelloServiceTest { @RountingInjected(value = "helloServiceImpl2") private HelloService helloService; public void testSayHello() { helloService.sayHello(); } public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("colin.spring.basic.advanced.bbp"); HelloServiceTest helloServiceTest = applicationContext.getBean(HelloServiceTest.class); helloServiceTest.testSayHello(); }}Copy the code

Four DisposableBean interfaces

Called when the Spring bean is destroyed, this is less commonly used, but is part of the lifecycle

Spring life cycle diagram

Six conclusion

If you contrast this with the Spring lifecycle diagram, you can see that the implementation of each interface is a part of the Spring lifecycle, and that these interfaces actually represent the flexibility of the Spring framework. Understanding these interfaces is a great help in using the Spring Framework.