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 原理图:
感谢观看,喜欢给个赞。