Spring - 手写模拟Spring底层原理

news/2024/10/20 3:21:03/

手写Spring

定义配置类AppConfig

@ComponentScan("com.spring.zsj")
public class AppConfig {@Beanpublic ApplicationListener applicationListener() {return new ApplicationListener() {@Overridepublic void onApplicationEvent(ApplicationEvent event) {System.out.println("接收到了一个事件"+event );}};}}

定义容器ZSJApplicationContext

public class ZSJApplicationContext {private Class configClass;private Map<String,BeanDefinition> beanDefinitionMap =new HashMap<>();//bean定义private Map<String,Object> singleObjects = new HashMap<>(); //单例池private List<BeanPostProcessor> beanPostProcessorList =new ArrayList<>(); //后置处理public ZSJApplicationContext(Class configClass)  {this.configClass = configClass;scanComponent(configClass);//找出单例beanfor (Map.Entry<String,BeanDefinition> entry: beanDefinitionMap.entrySet()) {String beanName = entry.getKey();BeanDefinition beanDefinition = entry.getValue();if(beanDefinition.equals("singleton")){Object bean = createBean(beanName, beanDefinition);singleObjects.put(beanName,bean);}}}private Object createBean(String beanName,BeanDefinition beanDefinition){Class clazz = beanDefinition.getType();Object newInstance = null;try {newInstance =  clazz.getConstructor().newInstance();//依赖注入for (Field field : clazz.getDeclaredFields()) {if (clazz.isAnnotationPresent(Autowired.class)) {field.setAccessible(true);field.set(newInstance, getBean(field.getName()));}}//执行回调方法if (newInstance instanceof  BeanNameAware){((BeanNameAware) newInstance).setBeanName(beanName);}//执行初始化前的方法for (BeanPostProcessor beanPostProcessor: beanPostProcessorList) {newInstance = beanPostProcessor.postProcessBeforeInitialization(newInstance, beanName);}//当前对象是否实例化了if(newInstance instanceof  InitializingBean){((InitializingBean) newInstance).afterPropertiesSet();}//执行初始化后的方法(例如Aop)for (BeanPostProcessor beanPostProcessor: beanPostProcessorList) {newInstance = beanPostProcessor.postProcessAfterInitialization(newInstance, beanName);}} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}return newInstance;}private void scanComponent(Class configClass) {if(configClass.isAnnotationPresent(ComponentScan.class)){ComponentScan annotation =(ComponentScan) configClass.getAnnotation(ComponentScan.class);String path = annotation.value();path = path.replace(".", "/");ClassLoader classLoader = ZSJApplicationContext.class.getClassLoader();URL resource = classLoader.getResource(path);File file = new File(resource.getFile());if(file.isDirectory()){//若是文件夹,则取出对应的文件for (File f: file.listFiles()) {String absolutePath = f.getAbsolutePath();//System.out.println(absolutePath);String com = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));String replace = com.replace("\\", ".");// System.out.println(replace);try {Class<?> clazz = classLoader.loadClass(replace);if(clazz.isAnnotationPresent(Component.class)){//clazz 是否实现了BeanPostProcessor接口if(BeanPostProcessor.class.isAssignableFrom(clazz)){BeanPostProcessor instance = (BeanPostProcessor)clazz.getConstructor().newInstance();beanPostProcessorList.add(instance);}//获取bean 的名字Component annotation1 = clazz.getAnnotation(Component.class);String beanName = annotation1.value();if("".equals(beanName)){String name = Introspector.decapitalize(clazz.getSimpleName());}BeanDefinition beanDefinition = new BeanDefinition();beanDefinition.setType(clazz);if(clazz.isAnnotationPresent(Scope.class)){//圆型的Scope scope = clazz.getAnnotation(Scope.class);String value = scope.value();beanDefinition.setScope(value);}else {//单例的beanDefinition.setScope("singleton");}beanDefinitionMap.put(beanName,beanDefinition);//   System.out.println(clazz);}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}}//   System.out.println(path);}}//通过bean名称获取bean对象public Object getBean(String beanName){if(!beanDefinitionMap.containsKey(beanName)){throw new NullPointerException();}BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);if(beanDefinition.getScope().equals("singleton")){Object singletonBean = singleObjects.get(beanName);if(singletonBean== null){singletonBean = createBean(beanName, beanDefinition);singleObjects.put(beanName,singletonBean);}return singletonBean;}else {//原型的Object prototypeBean = createBean(beanName, beanDefinition);return prototypeBean;}}
}

定义注解@Autowired  @Component  @Scope @ComponentScan

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {String value() default "";
}@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {String value() default "";
}@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {String value() default "";
}@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {String value() default "";
}

定义后置处理器BeanPostProcessor,用于初始化

public interface BeanPostProcessor {default Object postProcessBeforeInitialization(Object bean, String beanName)  {return bean;}default Object postProcessAfterInitialization(Object bean, String beanName) {return bean;}
}

   定义ZSJBeanPostProcessor实现BeanPostProcesso

@Component
public class ZSJBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {if(beanName.equals("userService")){Object proxyInstance = Proxy.newProxyInstance(ZSJBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//切面System.out.println("切面逻辑");return method.invoke(bean,args);}});return proxyInstance;}return bean;}
}

定义初始化接口InitializingBean

public interface InitializingBean {void afterPropertiesSet();
}

定义普通的类(可实例化成单例bean)

@Component("userService")
@Scope("singleton")
//public class UserService implements InitializingBean {
public class UserService implements UserInterface {@Autowiredprivate OrderService orderService;@ZSanValue("zhangsan")private String user;//圆型bean 表示多例beanpublic void test(){System.out.println(orderService);}//    @Override
//    public void afterPropertiesSet() {
//        System.out.println("初始化");
//    }
}

定义普通的类(可实例化成原型bean)

@Component("orderService")
@Scope("prototype")
public class OrderService {//圆型bean 表示多例beanpublic void test(){System.out.println("hello");}
}

定义启动类main


public class Test {public static void main(String[] args) {//非懒加载的单例bean
//        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
//        UserService userService = (UserService)context.getBean("userService");
//
//        userService.test();ZSJApplicationContext context = new ZSJApplicationContext(AppConfig.class);UserInterface userService = (UserInterface)context.getBean("userService");userService.test();//      System.out.println(context.getBean("userService"));
//        System.out.println(context.getBean("userService"));
//        System.out.println(context.getBean("userService"));
//        System.out.println(context.getBean("orderService"));
//        System.out.println(context.getBean("orderService"));
//        System.out.println(context.getBean("orderService"));//        AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context);
//        reader.register(User.class);
//        System.out.println(context.getBean("user"));StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();propertyEditor.setAsText("1");User value =new User();System.out.println(value);}
}

BeanPostProcesso扩展使用方法

自定义注解@ZSanValue

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ZSanValue {String value() default "";
}

使用注解时,将注解的值赋给属性:如

@ZSanValue("zhangsan")
private String user;

 实现后置处理器,并执行初始化前的操作,将自定义的注解值进行属性赋值

@Component
public class ZSanValueBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {for (Field field : bean.getClass().getDeclaredFields()) {if(field.isAnnotationPresent(ZSanValue.class)){field.setAccessible(true);try {field.set(bean,field.getAnnotation(ZSanValue.class).value());} catch (IllegalAccessException e) {e.printStackTrace();}}}return bean;}
}

回调方法使用BeanNameAware

定义回调接口

public interface BeanNameAware {void setBeanName(String name);
}

则实现类需要实现BeanNameAware接口

@Component("userService")
@Scope("singleton")
//public class UserService implements InitializingBean {
public class UserService implements UserInterface,BeanNameAware {@Autowiredprivate OrderService orderService;@ZSanValue("zhangsan")private String user;private String beanName;//圆型bean 表示多例beanpublic void test(){System.out.println(orderService);}@Overridepublic void setBeanName(String name) {this.beanName=name;}//    @Override
//    public void afterPropertiesSet() {
//        System.out.println("初始化");
//    }
}


http://www.ppmy.cn/news/1192188.html

相关文章

【flink】flink获取-D参数方式

参考官网 一、idea 本地运行 使用Flink官方的ParameterTool或者其他工具都可以。 二、集群运行flink run/run-application &#xff08;1&#xff09;ParameterTool 获取参数 以-D开头的参数&#xff1a; ParameterTool parameter ParameterTool.fromSystemProperties()…

大厂信息泄露-漏洞复现

目录 大唐电信AC简介 资产收集 漏洞复现 修复建议 免费领取安全学习资料包&#xff01;&#xff08;私聊进群一起学习&#xff0c;共同进步&#xff09;​编辑 大唐电信AC简介 大唐电信科技股份有限公司是电信科学技术研究院&#xff08;大唐电信科技产业集团&#xff09…

XSAN数据恢复-存储空间架构迁移时误格式化存储系统的XSAN数据恢复案例

XSAN数据恢复环境&#xff1a; 昆腾存储&#xff0c;MAC OS操作系统&#xff0c;存放视频类数据&#xff08;MXF、MOV等格式文件&#xff09;。 XSAN故障&检测&#xff1a; 将存储空间从XSAN架构迁移到STORNEXT架构后&#xff0c;存储空间中数据全部丢失。 故障存储中一共…

MATLAB野外观测站生态气象数据处理分析实践应用

1.基于MATLAB语言 2.以实践案例为主&#xff0c;提供所有代码 3.原理与操作结合 4.布置作业&#xff0c;答疑与拓展 示意图&#xff1a; 以野外观测站高频时序生态气象数据为例&#xff0c;基于MATLAB开展上机操作&#xff1a; 1.不同生态气象要素文件的数据读写与批处理实现 …

MySQL 权限表db、tables_priv、columns_priv和procs_priv

db表 db 表比较常用&#xff0c;是 MySQL 数据库中非常重要的权限表&#xff0c;表中存储了用户对某个数据库的操作权限。表中的字段大致可以分为两类&#xff0c;分别是用户列和权限列。 用户列 db 表用户列有 3 个字段&#xff0c;分别是 Host、User、Db&#xff0c;标识从…

文件字符流的使用

文件字符输入流 概述 文件字符输入流&#xff1a;FileReader。 作用&#xff1a;以内存为基准&#xff0c;把磁盘文件中的数据以字符的形式读取到内存中去。 为什么要用&#xff1f; 字节流读取中文时为了避免乱码需要一次性读到字节数组里&#xff0c;如果文件很大的话&a…

LeetCode 2103.环和杆

原题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 C代码 常规 class Solution { public:int countPoints(string rings) {int count 0;set<string>se[10];for(int i1,j0;i<rings.length();i2,j2){se[rings[i]-0].inser…