Blog: bugstack.cn

Precipitation, share, grow, let yourself and others can gain something! πŸ˜„

One, foreword

I can't understand the code written by my colleague!

A class implements multiple interfaces, inheriting classes that inherit from other classes, interfaces that inherit from interfaces, abstract classes that implement interfaces that implement abstract class methods, class B that inherits from class A implements interface C, and so on.

Looks complicated and hard to understand the code, but can meet the demand of efficient iterative and extend smoothly once again, and you like screw move brick, only in big write code, complete an interface of a small piece of functionality, even don’t know how to finish is called operation, the whole process like the Spring source, Jumping around in confusion!

In fact, this is mainly because your code is the use of the design pattern, of course, the design pattern is not so magical, like your two houses are 120 square meters of house, his house has three rooms, two halls, a kitchen and a bathroom, north-south transparent, full sun lighting. But your home is not the same, your home is POTS and pans, bathroom toilet, sofa tea table and that 1.8 double bed, in the 120 square meters of the house open put, no static isolation, no dry and wet separation, pure free play. So your code looks messy!

Second, the target

The Spring framework currently implemented can provide capabilities for Bean operations, including: BeanFactoryPostProcessor, BeanPostProcessor, InitializingBean, DisposableBean, And some new configuration processing in XML that makes Bean objects more operational.

So what if we want to get the Spring framework’s BeanFactory, ApplicationContext, BeanClassLoader, etc. So we want to provide an interface in the Spring framework that is aware of container operations, so that if you implement such an interface, you can get all kinds of capabilities in the interface’s input parameters.

Three, the design

If I want to get some resources provided by the Spring framework, I need to think about how to get them first, and then how to get them in the Spring framework. By implementing these two things, I can extend some of the capabilities that belong to the Spring framework itself.

During the Bean object instantiation phase we did some additional definitions, attributes, initializations, and destruction. In fact, we can also do this when we get Spring things like BeanFactory and ApplicationContext. So we need to define a token interface, this interface does not need to have a method, it just serves as a token function, and the specific function of the interface is defined by the other functional interface of the interface, and finally this interface can be determined and called through instanceof. The overall design structure is as follows:

  • Define the interface Aware, which in the Spring framework is a token Aware interface. Specific subclass definitions and implementations are Aware of related objects in the container.It is through this bridge that container services are provided to concrete implementation classes
  • Interfaces that inherit From Aware include: BeanFactoryAware, BeanClassLoaderAware, BeanNameAware, and ApplicationContextAware. There are other annotations in the Spring source code, but we don’t use them yet.
  • As you can see in the concrete interface implementation process, part of (BeanFactoryAware, BeanClassLoaderAware, BeanNameAwareIn the factory support folder, ApplicationContextAware is in context support, because different content fetching needs to be provided in different packages. So, in the concrete implementation of AbstractApplicationContext to add the beanFactory BeanPostProcessor content may be usedApplicationContextAwareProcessorWhen the operation, and finally founded by AbstractAutowireCapableBeanFactory createBean processing corresponding call operation.About applyBeanPostProcessorsBeforeInitialization has been implemented in the previous section, if you forget to forward pace

Four, implementation,

1. Engineering structure

Small - spring - step - 08 β”” ─ ─ the SRC β”œ ─ ─ the main β”‚ β”” ─ ─ Java β”‚ β”” ─ ─ cn. Bugstack. Springframework β”‚ β”œ ─ ─ beans β”‚ β”‚ β”œ ─ ─ factory β”‚ β”‚ β”‚ β”œ ─ ─ The factory β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ AutowireCapableBeanFactory. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ BeanDefinition. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ Spring BeanFactoryPostProcessor. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ BeanPostProcessor. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ BeanReference. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ ConfigurableBeanFactory. Java β”‚ β”‚ β”‚ β”‚ β”” ─ ─ SingletonBeanRegistry. Java β”‚ β”‚ β”‚ β”œ ─ ─ support β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ AbstractAutowireCapableBeanFactory. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ AbstractBeanDefinitionReader. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ AbstractBeanFactory. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ BeanDefinitionReader. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ BeanDefinitionRegistry. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ CglibSubclassingInstantiationStrategy. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ DefaultListableBeanFactory. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ DefaultSingletonBeanRegistry. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ DisposableBeanAdapter. Java β”‚ β”‚ β”‚ β”‚ β”œ ─ ─ InstantiationStrategy. Java β”‚ β”‚ β”‚ β”‚ β”” ─ ─ SimpleInstantiationStrategy. Java β”‚ β”‚ β”‚ β”œ ─ ─ support β”‚ β”‚ β”‚ β”‚ β”” ─ ─ XmlBeanDefinitionReader. Java β”‚ β”‚ β”‚ β”œ ─ ─ Aware. Java β”‚ β”‚ β”‚ β”œ ─ ─ BeanClassLoaderAware. Java β”‚ β”‚ β”‚ β”œ ─ ─ the BeanFactory. Java β”‚ β”‚ β”‚ β”œ ─ ─ BeanFactoryAware. Java β”‚ β”‚ β”‚ β”œ ─ ─ BeanNameAware. Java β”‚ β”‚ β”‚ β”œ ─ ─ ConfigurableListableBeanFactory. Java β”‚ β”‚ β”‚ β”œ ─ ─ DisposableBean. Java β”‚ β”‚ β”‚ β”œ ─ ─ HierarchicalBeanFactory. Java β”‚ β”‚ β”‚ β”œ ─ ─ InitializingBean. Java β”‚ β”‚ β”‚ β”” ─ ─ ListableBeanFactory. Java β”‚ β”‚ β”œ ─ ─ BeansException. Java β”‚ β”‚ β”œ ─ ─ PropertyValue. Java β”‚ β”‚ β”” ─ ─ PropertyValues. Java β”‚ β”œ ─ ─ the context β”‚ β”‚ β”œ ─ ─ support β”‚ β”‚ β”‚ β”œ ─ ─ AbstractApplicationContext. Java β”‚ β”‚ β”‚ β”œ ─ ─ AbstractRefreshableApplicationContext. Java β”‚ β”‚ β”‚ β”œ ─ ─ AbstractXmlApplicationContext. Java β”‚ β”‚ β”‚ β”œ ─ ─ ApplicationContextAwareProcessor. Java β”‚ β”‚ β”‚ β”” ─ ─ ClassPathXmlApplicationContext. Java β”‚ β”‚ β”œ ─ ─ ApplicationContext. Java β”‚ β”‚ β”œ ─ ─ ApplicationContextAware. Java β”‚ β”‚ β”” ─ ─ ConfigurableApplicationContext. Java β”‚ β”œ ─ ─ core. IO β”‚ β”‚ β”œ ─ ─ ClassPathResource. Java β”‚ β”‚ β”œ ─ ─ DefaultResourceLoader. Java β”‚ β”‚ β”œ ─ ─ FileSystemResource. Java β”‚ β”‚ β”œ ─ ─ the Resource. The Java β”‚ β”‚ β”œ ─ ─ ResourceLoader. Java β”‚ β”‚ β”” ─ ─ UrlResource. Java β”‚ β”” ─ ─ utils β”‚ β”” ─ ─ ClassUtils. Java β”” ─ ─ the test β”” ─ ─ Java β”” ─ ─ Cn. Bugstack. Springframework. Test β”œ ─ ─ bean β”‚ β”œ ─ ─ UserDao. Java β”‚ β”” ─ ─ UserService. Java β”” ─ ─ ApiTest. JavaCopy the code

Project source: public account “bugStack wormhole stack”, reply: Spring column, get the full source code

Design and implement class relationships for Spring aware interfaces, as shown in Figure 9-2

  • The whole class relation above is about the definition of Aware awareness and the realization of container awareness.
  • Aware has four inherited interfaces. The inheritance of the other interfaces is to inherit a tag. The existence of the tag is more convenient for the operation and concrete judgment implementation of the class.
  • And because the ApplicationContext are not in AbstractAutowireCapableBeanFactory createBean method under the content, so you need to register as the containeraddBeanPostProcessor, the createBean unified call applyBeanPostProcessorsBeforeInitialization operate.

2. Define the tag interface

cn.bugstack.springframework.beans.factory.Aware

/** * Marker superinterface indicating that a bean is eligible to be * notified by the Spring container of a particular framework object * through a callback-style method. Actual method signature is * determined by individual subinterfaces, Accepts a single * argument. Implementing this interface can be aware of by the Spring container
public interface Aware {}Copy the code
  • In Spring, there are a lot of ways to tag interfaces like this. They exist as a kind of tag that makes it easy to pull out the implementation classes that belong to this kind of interface, usually with instanceof.

3. Container aware classes

3.1 BeanFactoryAware

cn.bugstack.springframework.beans.factory.BeanFactoryAware

public interface BeanFactoryAware extends Aware {

   void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}
Copy the code
  • Interface to be implemented by beans that wish to be aware of their owning {@link BeanFactory}.
  • This interface is aware of the BeanFactory to which it belongs

3.2 BeanClassLoaderAware

cn.bugstack.springframework.beans.factory.BeanClassLoaderAware

public interface BeanClassLoaderAware extends Aware{

    void setBeanClassLoader(ClassLoader classLoader);

}
Copy the code
  • Callback that allows a bean to be aware of the bean{@link ClassLoader class loader}; that is, the class loader used by the present bean factory to load bean classes.
  • This interface is aware of the ClassLoader it belongs to

3.3 BeanNameAware

cn.bugstack.springframework.beans.factory.BeanNameAware

public interface BeanNameAware extends Aware {

    void setBeanName(String name);

}
Copy the code
  • Interface to be implemented by beans that want to be aware of their bean name in a bean factory.
  • This interface is aware of the BeanName to which it belongs

3.4 ApplicationContextAware

cn.bugstack.springframework.context.ApplicationContextAware

public interface ApplicationContextAware extends Aware {

    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}
Copy the code
  • Interface to be implemented by any object that wishes to be notifiedof the {@link ApplicationContext} that it runs in.
  • Implement this interface to be aware of the ApplicationContext to which it belongs

4. Packing processor (ApplicationContextAwareProcessor)

cn.bugstack.springframework.context.support.ApplicationContextAwareProcessor

public class ApplicationContextAwareProcessor implements BeanPostProcessor {

    private final ApplicationContext applicationContext;

    public ApplicationContextAwareProcessor(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof ApplicationContextAware){
            ((ApplicationContextAware) bean).setApplicationContext(applicationContext);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        returnbean; }}Copy the code
  • Since the fetch of the ApplicationContext is not directly available when the Bean is created, the ApplicationContext needs to be written to a wrapped BeanPostProcessor during the refresh operation. By AbstractAutowireCapableBeanFactory again. ApplyBeanPostProcessorsBeforeInitialization method call.

5. Registered BeanPostProcessor

cn.bugstack.springframework.context.support.AbstractApplicationContext

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

    @Override
    public void refresh(a) throws BeansException {
        // 1. Create BeanFactory and load BeanDefinition
        refreshBeanFactory();

        // 2. Get BeanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();

        / / 3. Add ApplicationContextAwareProcessor to inherit from object Bean ApplicationContextAware ApplicationContext can perceive belonged to
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

        BeanFactoryPostProcessor (Invoke Factory Registered as beans in the context.)
        invokeBeanFactoryPostProcessors(beanFactory);

        // 5. BeanPostProcessor needs to register before other Bean objects are instantiated
        registerBeanPostProcessors(beanFactory);

        // 6. Instantiate the singleton Bean object in advance
        beanFactory.preInstantiateSingletons();
    }
    
 	// ...   
}    
Copy the code
  • The refresh() method is the entire operation of the Spring container. In contrast to the previous section, the addBeanPostProcessor operation has been added.
  • Add ApplicationContextAwareProcessor to inherit from object Bean ApplicationContextAware ApplicationContext can perceive belonged to.

6. Perceive the call operation

cn.bugstack.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

    private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
        Object bean = null;
        try {
            bean = createBeanInstance(beanDefinition, beanName, args);
            // Populate the Bean with properties
            applyPropertyValues(beanName, bean, beanDefinition);
            // Executes the Bean initialization methods and the BeanPostProcessor pre - and post-processing methods
            bean = initializeBean(beanName, bean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Instantiation of bean failed", e);
        }

        // Register a Bean object that implements the DisposableBean interface
        registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);

        addSingleton(beanName, bean);
        return bean;
    }

    private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {

        // invokeAwareMethods
        if (bean instanceof Aware) {
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(this);
            }
            if (bean instanceof BeanClassLoaderAware){
                ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
            }
            if (bean instanceofBeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); }}// 1. Run BeanPostProcessor Before
        Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

        // Executes the Bean object's initialization method
        try {
            invokeInitMethods(beanName, wrappedBean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
        }

        // 2. Run the BeanPostProcessor After command
        wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
        return wrappedBean;
    }



    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (null == current) return result;
            result = current;
        }
        return result;
    }

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (null == current) return result;
            result = current;
        }
        returnresult; }}Copy the code
  • Here we have removed some of the classes, leaving only the operations on the Aware Aware interface.
  • First in the initializeBean, by judgmentbean instanceof Aware, calls three interface methods,BeanFactoryAware.setBeanFactory(this),BeanClassLoaderAware.setBeanClassLoader(getBeanClassLoader()),BeanNameAware.setBeanName(beanName), notifying classes that already implement this interface.
  • We also added to BeanPostProcessorApplicationContextAwareProcessorThat method is also called to the concrete class implementation to get an ApplicationContex property.

Five, the test

1. Prepare

cn.bugstack.springframework.test.bean.UserDao

public class UserDao {

    private static Map<String, String> hashMap = new HashMap<>();

    public void initDataMethod(a){
        System.out.println("Execute: init-method");
        hashMap.put("10001".Little Fuge.);
        hashMap.put("10002"."Eight glasses of water");
        hashMap.put("10003"."Will");
    }

    public void destroyDataMethod(a){
        System.out.println("Execute: destroy-method");
        hashMap.clear();
    }

    public String queryUserName(String uId) {
        returnhashMap.get(uId); }}Copy the code

cn.bugstack.springframework.test.bean.UserService

public class UserService implements BeanNameAware.BeanClassLoaderAware.ApplicationContextAware.BeanFactoryAware {

    private ApplicationContext applicationContext;
    private BeanFactory beanFactory;

    private String uId;
    private String company;
    private String location;
    private UserDao userDao;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("Bean Name is:" + name);
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("This." + classLoader);
    }

    / /... get/set
}
Copy the code
  • The UserDao does not change this time. It still provides methods for initialization and provides init-method and destroy-method configuration information in spring.xml.
  • UserService adds BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, and BeanFactoryAware, four aware implementation classes, and implements corresponding interface methods in the class.

2. Configuration file

Basic configuration, no BeanFactoryPostProcessor, BeanPostProcessor, and implementation class


      
<beans>

    <bean id="userDao" class="cn.bugstack.springframework.test.bean.UserDao" init-method="initDataMethod" destroy-method="destroyDataMethod"/>

    <bean id="userService" class="cn.bugstack.springframework.test.bean.UserService">
        <property name="uId" value="10001"/>
        <property name="company" value="Tencent"/>
        <property name="location" value="Shenzhen"/>
        <property name="userDao" ref="userDao"/>
    </bean>

</beans>
Copy the code
  • No additional configuration information is added in this section, which is the same as in the previous section.

Unit testing

@Test
public void test_xml(a) {
    1. Initialize the BeanFactory
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
    applicationContext.registerShutdownHook();      

    // 2. Get the Bean object to call the method
    UserService userService = applicationContext.getBean("userService", UserService.class);
    String result = userService.queryUserInfo();
    System.out.println("Test Results:" + result);
    System.out.println("ApplicationContextAware:"+userService.getApplicationContext());
    System.out.println("BeanFactoryAware:"+userService.getBeanFactory());
}
Copy the code
  • In the test method, a call about the new Aware implementation is added, and other logs that do not need to be called are also printed, which can be seen in the test results.

The test results

Init-method ClassLoader: sun.misc.Launcher$AppClassLoader@14dad5dc Bean Name is: userService Xiaofuge, Tencent, Shenzhen ApplicationContextAware: Cn. Bugstack. Springframework. Context. Support. ClassPathXmlApplicationContext @ 5 ba23b66 BeanFactoryAware: Cn. Bugstack. Springframework. Beans. Factory. Support. DefaultListableBeanFactory @ 2 ff4f00f implementation: destroy-method Process finished with exit code0
Copy the code
  • From the test results, it can be seen that the specific implementation (BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware) corresponding to the newly added perceptive interface in this chapter, The output is ready as expected.

Six, summarized

  • In the current implementation of the Spring framework, some function points are becoming more and more complete, especially the life cycle of Bean objects, which has been reflected a lot. Figure 9-3 shows the overall summary

  • This chapter is about the realization of BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware. It also extends Spring’s functionality. If you have done any Spring middleware development, you will use these classes a lot. Now that you have not only used them, but also know when they are touched, you will have a clear idea of the order in which classes are instantiated in the future.

  • The content of each chapter are realized in the design pattern as the core of the structure of filling the function of each module, simple operation code does not have too many harvest, must be to understand why such a design, what are the benefits of such a design, how so many interface and the application of the abstract class, which is the core of the Spring framework to study.

Seven, series recommendation

  • How many lines of code do I have to write after college to get a development job without spending money on training?
  • How do you become an architect when 90% of programmers have never used multithreading and locking?
  • Hold the grass! You poisoned the code!
  • Netty+JavaFx combat: imitation desktop version of wechat chat
  • Just the fire of the Taiwan turned on the demolition, a big wave of companies can not put and can not take up!