《Java Spring框架》Spring IOC 源码分析

1.下载源码

    源码部署:https://www.cnblogs.com/jssj/p/11631881.html

    并不强求,最好是有源码(方便理解和查问题)。

2. 创建子项目

    Spring项目中创建子项目:https://www.cnblogs.com/jssj/p/12329839.html

3. 案例(两个干预Spring生成Bean)

AppConfig:

package accelerate.app;

import org.springframework.context.annotation.ComponentScan;
        import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("accelerate")
public class AppConfig {
}

Apple

package accelerate.bean;

import org.springframework.stereotype.Component;

@Component
public class Apple {
    public Apple(){
        System.out.println("Apple");
    }
}

Test

package accelerate.bean;

public class Test {
    public Test(){
        System.out.println("构造方法-Test");
    }
}

AccelerateBeanFactoryPostProcessor

package accelerate.mybatis;

import accelerate.bean.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;

@Component
public class AccelerateBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        GenericBeanDefinition genericBeanDefinition = (GenericBeanDefinition)beanFactory.getBeanDefinition("apple");
        System.out.println("插手前:" + genericBeanDefinition.getBeanClassName());
        genericBeanDefinition.setBeanClass(Test.class);
    }
}

Demo

package accelerate.test;

import accelerate.app.AppConfig;
import accelerate.bean.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Demo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext(AppConfig.class);

        System.out.println("最终生成的Bean:"+ annotationConfigApplicationContext.getBean("apple"));
    }
}

build.gradle 

group 'org.springframework'
version '3.2.19.BUILD-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile project(':spring-context')
    compile project(':spring-beans')

}

运行结果:

结论: Apple类加了注解@Compnent而Test类没有加注解,最后通过getBean(Test.class)却拿到了Apple这个Bean对象。

根据调试:看到Spring源码AbstractApplicationContext 类有如下代码循环调用。

   /**
     * author hubt
     * 该代码执行循环执行实现BeanFactoryPostProcessor的类的方法。
     * @param postProcessors
     * @param beanFactory
     */
    private void invokeBeanFactoryPostProcessors(
            Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

        for (BeanFactoryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanFactory(beanFactory);
        }
    }

如何修改干预Spring生成Bean的过程。

/**
     * author
     * Spring会将Bean的信息(类名,修饰符等等)写入BeanDefinition类中,并将这些BeanDefinition存放入beanDefinitionMap中。
     * 该方法是根据你定义的名称获取对应存放bean信息的BeanDefinition。
     * @param beanName name of the bean to find a definition for
     * @return
     * @throws NoSuchBeanDefinitionException
     */
    @Override
    public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
        BeanDefinition bd = this.beanDefinitionMap.get(beanName);
        if (bd == null) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("No bean named '" + beanName + "' found in " + this);
            }
            throw new NoSuchBeanDefinitionException(beanName);
        }
        return bd;
    }

案例二:

AppConfig

package accelerate.app;

import org.springframework.context.annotation.ComponentScan;
        import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("accelerate")
public class AppConfig {
}

AopTest

package accelerate.mybatis;

import accelerate.service.AccelerateInvocationHandler;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Proxy;

@Component
public class AopTest implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("cityService")){
            Class<?> aClass = bean.getClass().getInterfaces()[0];
            Class[] classes = new Class[]{aClass};
            Object o = Proxy.newProxyInstance(AopTest.class.getClassLoader(), classes, new AccelerateInvocationHandler(bean));
            return o;
        }
        return bean;
    }
}

AccelerateInvocationHandler

package accelerate.service;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class AccelerateInvocationHandler implements InvocationHandler {

    Object o;

    public AccelerateInvocationHandler(Object o){
        this.o = o;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("aop----before");
        Object result = method.invoke(o);
        System.out.println("aop----after");
        return result;
    }
}

CityService

package accelerate.service;

import org.springframework.stereotype.Component;

@Component("cityService")
public class CityService implements L {

    public CityService(){
        System.out.println("构造方法----CityService");
    }

    public void query() {
        System.out.println("logic---db");
    }
}

L

package accelerate.service;

public interface L {
    public void query();
}

Demo

package accelerate.test;

import accelerate.app.AppConfig;
import accelerate.service.L;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Demo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext(AppConfig.class);

        L bean = annotationConfigApplicationContext.getBean(L.class);
        bean.query();
    }
}

build.gradle   配置不变。

运行结果:

结论:原本CityService只是一个普通Bean,被修改成一个代理类。

源码分析如下:

    /**
     * author hubt
     * 循环执行Spring的后置处理,也就是说实现或者继承BeanPostProcessors的类都会在这里被运用到
     * @param existingBean the new bean instance
     * @param beanName the name of the bean
     * @return
     * @throws BeansException
     */
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessAfterInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }

这边还运用了Java动态代理:https://www.cnblogs.com/jssj/p/11771408.html

Spring IOC 原理图:

 感谢观看,喜欢给个赞。

猜你喜欢

转载自www.cnblogs.com/jssj/p/12373275.html