如何实现手写模拟Spring底层原理的扫描、创建单例原型bean等操作?
摘要:代码结构 模拟spring源码 BeanDefinition public class BeanDefinition { private Class aClass; private String scope; private Boolean
代码结构
模拟spring源码
BeanDefinition
public class BeanDefinition {
private Class aClass;
private String scope;
private Boolean lazy;
public Class getaClass() {
return aClass;
}
public void setaClass(Class aClass) {
this.aClass = aClass;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public Boolean getLazy() {
return lazy;
}
public void setLazy(Boolean lazy) {
this.lazy = lazy;
}
}
BeanNameAware
public interface BeanNameAware {
void setBeanName(String beanName);
}
BeanPostProcessor
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
/**
* 初始化后,创建bean的过程中,每一个bean都会调用此方法,也可以单独判断,可以用来实现aop
*/
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
InitializingBean
public interface InitializingBean {
void afterPropertiesSet();
}
MyApplicationContext
public class MyApplicationContext {
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
//单例池
private Map<String, Object> singletonObjects = new HashMap<>();
private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
public MyApplicationContext(Class<MyAppConfig> myAppConfigClass) throws ClassNotFoundException, NoSuchMethodException {
//扫描 构建Bean定义,放在beanDefinitionMap中
scan(myAppConfigClass);
//扫描完,遍历beanDefinitionMap,找出所有的单例bean,创建单例bean并放在单例池中
//单例模式先创建bean再放在单例池中
Set<Map.Entry<String, BeanDefinition>> entries = beanDefinitionMap.entrySet();
for (Map.Entry<String, BeanDefinition> entry : entries) {
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
String scope = beanDefinition.getScope();
if ("singleton".equals(scope)) {
Object singletonBean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, singletonBean);
}
}
}
private void scan(Class<?> myAppConfigClass) throws ClassNotFoundException {
if (myAppConfigClass.isAnnotationPresent(MyComponentScan.class)) {
MyComponentScan annotation = myAppConfigClass.getAnnotation(MyComponentScan.class);
//扫描路径
String path = annotation.value();
System.out.println("扫描路径:" + path);
path = path.replace(".", "/");
ClassLoader classLoader = MyApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File fileDirectory = new File(resource.getFile());
if (fileDirectory.isDirectory()) {
File[] files = fileDirectory.listFiles();
//遍历class文件
for (File file : files) {
String absolutePath = file.getAbsolutePath();
//System.out.println("absolutePath->" + absolutePath);
//加载类
//转换路径格式
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.lastIndexOf(".class"));
absolutePath = absolutePath.replace("\\", ".");
//System.out.println("absolutePath->" + absolutePath);
//class文件加载为class对象
//Class<?> aClass = Class.forName(absolutePath);
Class<?> aClass = classLoader.loadClass(absolutePath);
//找到有Component注解的类
if (aClass.isAnnotationPresent(MyComponent.class)) {
System.out.println(absolutePath + "有component注解");
//如果一个类有component注解,再判断是否实现了BeanPostProcessor接口
if (BeanPostProcessor.class.isAssignableFrom(aClass)) {
try {
BeanPostProcessor instance = (BeanPostProcessor) aClass.getConstructor().newInstance();
//保存BeanPostProcessor,等到创建bean的时候再使用
beanPostProcessorList.add(instance);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//不用获取BeanPostProcessor的BeanDefinition
} else {
MyComponent myComponent = aClass.getAnnotation(MyComponent.class);
//注解中配置的beanName
String beanName = myComponent.value();
//如果未指定beanName
if ("".equals(beanName)) {
//根据类型生成名字
beanName = Introspector.decapitalize(aClass.getSimpleName());
}
//如果有类有Component这个注解,那么需要创建一个BeanDefinition描述该bean
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setaClass(aClass);
//再判断是单例还是原型
if (aClass.isAnnotationPresent(MyScope.class)) {
MyScope myScope = aClass.getAnnotation(MyScope.class);
String scope = myScope.value();
beanDefinition.setScope(scope);
} else {
//没有注解,默认是单例,如果是单例
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
}
}
}
}
}
public Object getBean(String beanName) throws NoSuchMethodException {
//如果没有则说明没有定义这个bean
if (!beanDefinitionMap.containsKey(beanName)) {
System.out.println("找不到该bean");
return null;
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
String scope = beanDefinition.getScope();
//如果是单例,直接从单例池中获取
if ("singleton".equals(scope)) {
Object singletonBean = singletonObjects.get(beanName);
//可能因为扫描顺序问题,还没有初始化成功
if (singletonBean == null) {
singletonBean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, singletonBean);
}
return singletonBean;
} else {
//原型模式每次都要重新创建
Object prototypeBean = createBean(beanName, beanDefinition);
return prototypeBean;
}
}
//创建bean
public Object createBean(String beanName, BeanDefinition beanDefinition) throws NoSuchMethodException {
Class aClass = beanDefinition.getaClass();
//调用构造方法创建对象
Object instance = null;
try {
instance = aClass.getConstructor().newInstance();
//创建bean的过程中进行依赖注入
//遍历类的属性
Field[] fields = aClass.getDeclaredFields();
for (Field field : fields) {
//判断属性上是否有autowired注解
if (field.isAnnotationPresent(MyAutowired.class)) {
field.setAccessible(true);
//赋值 -> 先根据类型再根据名字去找,我们这里只使用名字去找 会有循环依赖问题
field.set(instance, getBean(field.getName()));
}
}
//依赖注入完成后,beanNameAware
if (instance instanceof BeanNameAware) {
((BeanNameAware) instance).setBeanName(beanName);
}
//初始化前
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
//依赖注入完成之后进行初始化操作
//判断是否实现了InitializingBean接口
if (instance instanceof InitializingBean) {
((InitializingBean) instance).afterPropertiesSet();
}
//初始化后
//new MyBeanPostProcessor().postProcessAfterInitialization(instance, beanName);
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return instance;
}
}
MyAutowired
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAutowired {
String value() default "";
}
MyComponent
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyComponent {
String value() default "";
}
MyComponentScan
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyComponentScan {
String value() default "";
}
MyScope
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyScope {
String value() default "";
}
测试代码
MyAppConfig
@MyComponentScan("com.sy.test")
public class MyAppConfig {
}
MyBeanPostProcessor
@MyComponent
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
//创建bean的过程中,每一个bean都会调用此方法,也可以单独判断
if ("orderService".equals(beanName)) {
System.out.println("生成orderService的代理对象");
Object proxyInstance = Proxy.newProxyInstance(MyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//切面逻辑
System.out.println(beanName + "执行切面逻辑");
return method.invoke(bean, args);
}
});
return proxyInstance;
} else {
System.out.println(beanName + "执行bean的后置处理器");
return bean;
}
}
}
MyValue
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyValue {
String value() default "";
}
MyValueBeanPostProcessor
@MyComponent
public class MyValueBeanPostProcessor implements BeanPostProcessor {
/**
* 测试通过自定义注解给属性赋值
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
Field[] declaredFields = bean.getClass().getDeclaredFields();
for (Field field : declaredFields) {
if (field.isAnnotationPresent(MyValue.class)) {
field.setAccessible(true);
MyValue annotation = field.getAnnotation(MyValue.class);
String value = annotation.value();
try {
field.set(bean,value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return bean;
}
}
OrderInterface
public interface OrderInterface {
void test();
}
OrderService
@MyComponent
@MyScope("prototype")
public class OrderService implements OrderInterface, InitializingBean {
@MyAutowired
private UserService userService;
@MyValue("xxxxxx")
private String testStr;
@Override
public void test() {
System.out.println("myOrderService.test..........");
System.out.println("myOrderService.myUserService->" + userService);
System.out.println("myOrderService.testStr->" + testStr);
}
@Override
public void afterPropertiesSet() {
System.out.println("myOrderService.afterPropertiesSet...");
}
}
UserService
@MyScope("singleton")
@MyComponent("userService")
public class UserService implements InitializingBean, BeanNameAware {
private String beanName;
public void test() {
System.out.println("myUserService.test..............");
}
@Override
public void afterPropertiesSet() {
System.out.println("myUserService.afterPropertiesSet...");
}
@Override
public void setBeanName(String beanName) {
System.out.println("userService.setBeanName...");
this.beanName = beanName;
}
}
TestSpring
public class TestSpring {
@Test
public void testCreateBean() throws ClassNotFoundException, NoSuchMethodException {
//首先扫描 -> 创建单例bean BeanDefinition BeanPostProcessor
MyApplicationContext applicationContent = new MyApplicationContext(MyAppConfig.class);
UserService userService = (UserService) applicationContent.getBean("userService");
userService.test();
System.out.println("userService->" + applicationContent.getBean("userService"));
System.out.println("userService->" + applicationContent.getBean("userService"));
OrderInterface orderService = (OrderInterface) applicationContent.getBean("orderService");
orderService.test();
System.out.println("orderService->" + applicationContent.getBean("orderService"));
System.out.println("orderService->" + applicationContent.getBean("orderService"));
}
}
测试结果
源码下载
spring_sy.rar
