package com.xkj.org.a05;
import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
@ComponentScan("com.xkj.org.a05.component")
public class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
@Bean
public DruidDataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
}
package com.xkj.org.a05.component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class Bean2 {
private static final Logger log = LoggerFactory.getLogger(Bean2.class);
public Bean2() {
log.debug("我被Spring管理啦");
}
}
package com.xkj.org.a05.component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class Bean3 {
private static final Logger log = LoggerFactory.getLogger(Bean3.class);
public Bean3() {
log.debug("我被Spring管理啦");
}
}
package com.xkj.org.a05;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;
import java.io.IOException;
public class A05Application {
private static final Logger log = LoggerFactory.getLogger(A05Application.class);
public static void main(String[] args) throws IOException {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("config", Config.class);
// //bean工厂后置处理器
// context.registerBean(ConfigurationClassPostProcessor.class);
// //bean工厂后置处理器,第二个参数指定扫描的包(很少使用)
// context.registerBean(MapperScannerConfigurer.class, bd -> {
// bd.getPropertyValues().add("basePackage", "com.xkj.org.a05.mapper");
// });
// 去寻找@ComponentScan注解
ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
if(componentScan != null) {
// 找到需要扫描的包有哪些
for (String basePackage : componentScan.basePackages()) {
System.out.println("basePackage="+basePackage);
// com.xkj.org.a05.component -> classpath*:com/xkj/org/a05/component/**/*.class
// 将class文件的包路径 转化成 文件路径
String path = "classpath*:" + basePackage.replace(".", "/") + "/**/*.class";
// path=classpath*:com/xkj/org/a05/component/**/*.class
System.out.println("path="+path);
// 读取类的元信息的工厂
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
Resource[] resources = context.getResources(path);
AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
for (Resource resource: resources) {
// resource=file [D:\projects\reggie_take_out\target\classes\com\xkj\org\a05\component\Bean2.class]
System.out.println("resource=" + resource);
MetadataReader reader = factory.getMetadataReader(resource);
// 得到类信息
ClassMetadata classMetadata = reader.getClassMetadata();
System.out.println("类名:"+classMetadata.getClassName());
// 得到注解信息
AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
// 判断是否有@Component注解
System.out.println("是否存在@Component注解:"+
annotationMetadata.hasAnnotation(Component.class.getName()));
System.out.println("是否存在@Component注解,甚至是派生的,就是间接加了@Component注解的(@Controller)==="+
annotationMetadata.hasMetaAnnotation(Component.class.getName()));
if(annotationMetadata.hasAnnotation(Component.class.getName())
|| annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName())
.getBeanDefinition();
String beanName = generator.generateBeanName(beanDefinition, context.getDefaultListableBeanFactory());
context.getDefaultListableBeanFactory().registerBeanDefinition(beanName, beanDefinition);
}
}
}
}
context.refresh();
for (String name: context.getBeanDefinitionNames()) {
System.out.println("beanDefinitionName ="+name);
}
context.close();
}
}
方法抽取:
package com.xkj.org.a05;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericApplicationContext;
public class A05Application {
private static final Logger log = LoggerFactory.getLogger(A05Application.class);
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("config", Config.class);
//注册bean工厂的后置处理器
context.registerBean(ComponentScanPostProcessor.class);
context.refresh();
for (String name: context.getBeanDefinitionNames()) {
System.out.println("beanDefinitionName ="+name);
}
context.close();
}
}
package com.xkj.org.a05;
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.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;
public class ComponentScanPostProcessor implements BeanFactoryPostProcessor {
/**
* 此方法会在context.refresh时候调用
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
try {
// 去寻找@ComponentScan注解
ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
if(componentScan != null) {
// 找到需要扫描的包有哪些
for (String basePackage : componentScan.basePackages()) {
System.out.println("basePackage="+basePackage);
// com.xkj.org.a05.component -> classpath*:com/xkj/org/a05/component/**/*.class
// 将class文件的包路径 转化成 文件路径
String path = "classpath*:" + basePackage.replace(".", "/") + "/**/*.class";
// path=classpath*:com/xkj/org/a05/component/**/*.class
System.out.println("path="+path);
// 读取类的元信息的工厂
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
// 这里不再不使用context对象,换一种实现方式
Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
for (Resource resource: resources) {
// resource=file [D:\projects\reggie_take_out\target\classes\com\xkj\org\a05\component\Bean2.class]
System.out.println("resource=" + resource);
MetadataReader reader = factory.getMetadataReader(resource);
// 得到类信息
ClassMetadata classMetadata = reader.getClassMetadata();
System.out.println("类名:"+classMetadata.getClassName());
// 得到注解信息
AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
// 判断是否有@Component注解
System.out.println("是否存在@Component注解:"+
annotationMetadata.hasAnnotation(Component.class.getName()));
System.out.println("是否存在@Component注解,甚至是派生的,就是间接加了@Component注解的(@Controller)==="+
annotationMetadata.hasMetaAnnotation(Component.class.getName()));
if(annotationMetadata.hasAnnotation(Component.class.getName())
|| annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName())
.getBeanDefinition();
if(configurableListableBeanFactory instanceof DefaultListableBeanFactory) {
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)configurableListableBeanFactory;
String beanName = generator.generateBeanName(beanDefinition, beanFactory);
beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
}
}
}
}
}catch (Exception e) {
e.printStackTrace();
}
}
}