第一步:定义的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));
}