Spring中ImportBeanDefinitionRegistrar源码和使用

第一步:定义的Mapper层:

@Mapper
public interface PayMapper {

	@Select("select * from city")
	public List<Map<String,Object>> list();
}

第二步:使用FactoryBean,通过getObject方式,创建一个对象,放入到spring容器中,这里使用代理对象,放入到spring容器中。

public class MyFactoryBean implements FactoryBean, InvocationHandler {
	private Class aClass;

	public MyFactoryBean(Class aClass) {
		this.aClass = aClass;
	}

	@Override
	public Object getObject() throws Exception {
		Class[] interfaces = new Class[]{aClass};
		Object proxyInstance = Proxy.newProxyInstance(this.getClass().getClassLoader(), interfaces, this);
		return proxyInstance;
	}

	@Override
	public Class<?> getObjectType() {
		return null;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("代理对象,获取sql语句");
		Method method1 = proxy.getClass().getInterfaces()[0].getMethod(method.getName(), null);
		Select declaredAnnotation = method1.getDeclaredAnnotation(Select.class);
		System.out.println(declaredAnnotation.value()[0]);
		return null;
	}
}

第三步:
spring的ImportBeanDefinitionRegistrar处理器,可以对于spring的BeanDefinitionMap进行操作,可以修改Bean的描述,此时还没有变成对象,这里是把创建注入的类型,创建了构造方法中需要的接口,最后取Bean的名字:payServiceTest,一个BeanDefinition描述。

public class MyImportDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(PayMapper.class);
		AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
		//TODO: 注入类型
		beanDefinition.setBeanClass(MyFactoryBean.class);
		//TODO: 注入构造方法
		beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("com.luoyan.dao.mapper.PayMapper");
		//TODO: 放入到beanDefinitionMap中
		registry.registerBeanDefinition("payServiceTest",beanDefinition);
	}
}

第四步:自定义注解,把@Import(MyImportDefinitionRegistrar.class)注解,MyImportDefinitionRegistrar类放入到sprinig中运行。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MyImportDefinitionRegistrar.class)
public @interface LuoyanImportBeanDefinitionRegistrar {
}

第五步:配置类:需要使用自定义注解@LuoyanImportBeanDefinitionRegistrar,把后置处理器的代码内容执行。

@Configuration
@ComponentScan("com.luoyan")
@MapperScan("com.luoyan.dao.mapper")
@LuoyanImportBeanDefinitionRegistrar
public class AppConfig {
	
}

第六步:启动类:

public static void main(String[] args) {
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
	applicationContext.register(AppConfig.class);
	applicationContext.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
	applicationContext.refresh();

	PayMapper payServiceTest = (PayMapper) applicationContext.getBean("payServiceTest");
	payServiceTest.list();
}

源码:

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
		Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
		boolean checkForCircularImports) {

	if (importCandidates.isEmpty()) {
		return;
	}

	if (checkForCircularImports && isChainedImportOnStack(configClass)) {
		this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
	}
	else {
		this.importStack.push(configClass);
		try {
			/**
			 *
			 * 因为@Import(xxx.class,xxxx.class)这里可以放多个
			 * importCandidates:表示被放在@Import注解中的class类的报名+类名。比如:com.shadow.imports.MyImportSelector.
			 * candidate:就表示com.shadow.imports.MyImportSelector
			 */
			for (SourceClass candidate : importCandidates) {
				/**
				 * ImportSelector,判断这个MyImportSelector.class是否实现了ImportSelector类
				 */
				if (candidate.isAssignable(ImportSelector.class)) {
					// Candidate class is an ImportSelector -> delegate to it to determine imports
					//得到Import的类loadClass
					Class<?> candidateClass = candidate.loadClass();
					//反射实现一个对象
					//这个instantiateClass()方法底层比较复杂
					/******************************instantiateClass()这个方法很重要*************************************/
					//new出来当前实现了ImportSelector接口的类对象
					ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
							this.environment, this.resourceLoader, this.registry);
					Predicate<String> selectorFilter = selector.getExclusionFilter();
					if (selectorFilter != null) {
						exclusionFilter = exclusionFilter.or(selectorFilter);
					}
					if (selector instanceof DeferredImportSelector) {
						this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
					}
					else {
						/**
						 * 这里重点
						 * 普通类就是加了@component类
						 */
						//得到所有字符串.//循环引用这类用的是递归,就是说你配置类上有了@Impont,但是你实现了ImportSelector类的类上还是有@Impont
						//TODO: selector表示你实现ImportSelector接口的类的对象.
						String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
						//把名字传入得到importSourceClasses,把这个类添加到annotation这个变量中去了asSourceClasses()这个方法.
						//importClassNames=com.shadow.service.TestService3
						Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
						//然后又进行循环判断了.继续调用processImports()方法,刚刚进来的时候也是这个方法.
						//递归,这里第二次调用processImports.
						//如果是一个普通类,会进else
						processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
					}
				}
				/**
				 * ImportBeanDefinitionRegistrar实现了这个接口的类放到了addImportBeanDefinitionRegistrar()方法
				 * importBeanDefinitionRegistrarsMap当中去了。
				 * 而
				 * 实现ImportSelector接口的类却放到了configurationClassesMap当中去了。
				 * 所以在解析这些类的时候使用了不同的方法存放this.reader.loadBeanDefinitions(configClasses);
				 *
				 */
				else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
					// Candidate class is an ImportBeanDefinitionRegistrar ->
					// delegate to it to register additional com.luoyan.bean definitions
					Class<?> candidateClass = candidate.loadClass();
					ImportBeanDefinitionRegistrar registrar =
							ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
									this.environment, this.resourceLoader, this.registry);
					configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
				}
				/**
				 * 普通的
				 */
				else {
					// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
					// process it as an @Configuration class
					/**
					 * 否则,加入到importStack后调用processConfigurationClass进行处理
					 * processConfiguration里面主要就是把类放到configrationClasses
					 * 可以看到普通类再扫描出来的时候就被注册了
					 * 如果importSelector,回显放到configurationClasses后面进行注册
					 * 注意这里的processConfigurationClass前面已经解释过这个方法了
					 */
					this.importStack.registerImport(
							currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
					//processConfigurationClass()这个方法,是继续判断当前普通类是否加了@Configuration注解
					//candidate.asConfigClass(configClass)这个方法,是把通过@Import注解得到的类,执行方法后,得到返回回来的类字符串,反射出来的类.放入到this.importedBy.add(importedBy);集合中
					//真正导入到spring的BeanDefinitionMap中的时候使用到
					processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
				}
			}
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanDefinitionStoreException(
					"Failed to process import candidates for configuration class [" +
					configClass.getMetadata().getClassName() + "]", ex);
		}
		finally {
			this.importStack.pop();
		}
	}
}

源码:

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
	registrars.forEach((registrar, metadata) ->
			/**
			 * 这个registrar.registerBeanDefinitions就是自己实现了ImportBeanDefinitionRegistrar接口
			 * 的类中逻辑,注册到beanMap中的方法
			 */
			registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值