当前位置: 首页 > news >正文

开发网站教程常用的平面设计软件有哪些

开发网站教程,常用的平面设计软件有哪些,wordpress标签 扩展,无极网最新招聘信息浅入浅出Spring架构设计 前言 为什么需要Spring? 什么是Spring? 对于这样的问题#xff0c;大部分人都是处于一种朦朦胧胧的状态#xff0c;说的出来#xff0c;但又不是完全说的出来#xff0c;今天我们就以架构设计的角度尝试解开Spring的神秘面纱。 本篇文章以由浅…浅入浅出Spring架构设计 前言 为什么需要Spring? 什么是Spring? 对于这样的问题大部分人都是处于一种朦朦胧胧的状态说的出来但又不是完全说的出来今天我们就以架构设计的角度尝试解开Spring的神秘面纱。 本篇文章以由浅入深的方式进行介绍大家不必惊慌我可以保证只要你会编程就能看懂。 本篇文章基于Spring 5.2.8阅读时长大概需要20分钟 案例 我们先来看一个案例有一个小伙有一辆吉利车 平常就开吉利车上班 代码实现 java复制代码public class GeelyCar {public void run(){System.out.println(geely running);} } java复制代码public class Boy {// 依赖GeelyCarprivate final GeelyCar geelyCar new GeelyCar();public void drive(){geelyCar.run();} }有一天小伙赚钱了又买了辆红旗想开新车。 简单把依赖换成HongQiCar 代码实现 java复制代码public class HongQiCar {public void run(){System.out.println(hongqi running);} } java复制代码public class Boy {// 修改依赖为HongQiCarprivate final HongQiCar hongQiCar new HongQiCar();public void drive(){hongQiCar.run();} }新车开腻了又想换回老车这时候就会出现一个问题这个代码一直在改来改去 很显然这个案例违背了我们的依赖倒置原则(DIP):程序不应依赖于实现而应依赖于抽象 优化后 现在我们对代码进行如下优化 Boy依赖于Car接口而之前的GeelyCar与HongQiCar为Car接口实现 代码实现 定义出Car接口 java复制代码public interface Car {void run(); }将之前的GeelyCar与HongQiCar改为Car的实现类 java复制代码public class GeelyCar implements Car {Overridepublic void run(){System.out.println(geely running);} }HongQiCar相同 Person此时依赖的为Car接口 java复制代码public class Boy {// 依赖于接口private final Car car;public Person(Car car){this.car car;}public void drive(){car.run();} }此时小伙想换什么车开就传入什么参数即可代码不再发生变化。 局限性 以上案例改造后看起来确实没有什么毛病了但还是存在一定的局限性如果此时增加新的场景 有一天小伙喝酒了没法开车需要找个代驾。代驾并不关心他给哪个小伙开车也不关心开的是什么车小伙就突然成了个抽象这时代码又要进行改动了代驾依赖小伙的代码可能会长这个样子 java 复制代码private final Boy boy new YoungBoy(new HongQiCar());随着系统的复杂度增加这样的问题就会越来越多越来越难以维护那么我们应当如何解决这个问题呢 思考 首先我们可以肯定使用依赖倒置原则是没有问题的它在一定程度上解决了我们的问题。 我们觉得出问题的地方是在传入参数的过程程序需要什么我们就传入什么一但系统中出现多重依赖的类关系这个传入的参数就会变得极其复杂。 或许我们可以把思路反转一下我们有什么程序就用什么 当我们只实现HongQiCar和YoungBoy时代驾就使用的是开着HongQiCar的YoungBoy 当我们只实现GeelyCar和OldBoy时代驾自然而然就改变成了开着GeelyCar的OldBoy 而如何反转就是Spring所解决的一大难题。 Spring介绍 Spring是一个一站式轻量级重量级的开发框架目的是为了解决企业级应用开发的复杂性它为开发Java应用程序提供全面的基础架构支持让Java开发者不再需要关心类与类之间的依赖关系可以专注的开发应用程序(crud)。 Spring为企业级开发提供给了丰富的功能而这些功能的底层都依赖于它的两个核心特性:依赖注入(DI)和面向切面编程(AOP)。 Spring的核心概念 IoC容器 IoC的全称为Inversion of Control 意为控制反转IoC也被称为依赖性注入(DI)这是一个通过依赖注入对象的过程对象仅通过构造函数、工厂方法或者在对象实例化在其上设置的属性来定义其依赖关系(即与它们组合的其他对象)然后容器在创建bean时注入这些需要的依赖。这个过程从根本上说是Bean本身通过使用直接构建类或诸如服务定位模式的机制来控制其依赖关系的实例化或位置的逆过程因此被称为控制反转。 依赖倒置原则是IoC的设计原理依赖注入是IoC的实现方式。 容器 在Spring中我们可以使用XML、Java注解或Java代码的方式来编写配置信息而通过配置信息获取有关实例化、配置和组装对象的说明进行实例化、配置和组装应用对象的称为容器。 一般情况下我们只需要添加几个注解这样容器进行创建和初始化后我们就可以得到一个可配置的可执行的系统或应用程序。 Bean 在Spring中由Spring IOC容器进行实例化—组装管理—构成程序骨架的对象称为Bean。Bean就是应用程序中众多对象之一。 以上三点串起来就是Spring内部是一个放置Bean的IoC容器通过依赖注入的方式处理Bean之间的依赖关系。 AOP 面向切面编程(Aspect-oriented Programming)是相对面向对象编程(OOP)的一种功能补充,OOP面向的主要对象是类而AOP则是切面。在处理日志、安全管理、事务管理等方面有非常重要的作用。AOP是Spring框架重要的组件虽然IOC容器没有依赖AOP但是AOP提供了非常强大的功能用来对IOC做补充。 AOP可以让我们在不修改原有代码的情况下对我们的业务功能进行增强将一段功能切入到我们指定的位置如在方法的调用链之间打印日志。 Spring的优点 1、Spring通过DI、AOP来简化企业级Java开发 2、Spring的低侵入式设计让代码的污染极低 3、Spring的IoC容器降低了业务对象之间的复杂性让组件之间互相解耦 4、Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式处理从而提高了更好的复用性 5、Spring的高度开放性并不强制应用完全依赖于Spring开发者可自由选用Spring框架的部分或全部 6、Spring的高度扩展性让开发者可以轻易的让自己的框架在Spring上进行集成 7、Spring的生态极其完整集成了各种优秀的框架让开发者可以轻易的使用它们 我们可以没有Java但是不能没有Spring~ 用Spring改造案例 我们现在已经认识了什么是Spring现在就尝试使用Spring对案例进行改造一下 原来的结构没有变化只需在GeelyCar或HongQiCar上增加Component注解Boy在使用时加上Autowired注解 代码样式 java复制代码Component public class GeelyCar implements Car {Overridepublic void run() {System.out.println(geely car running);} }HongQiCar相同 在Spring中当类标识了Component注解后就表示这是一个Bean可以被IoC容器所管理 java复制代码Component public class Boy {// 使用Autowired注解表示car需要进行依赖注入Autowiredprivate Car car;public void driver(){car.run();} }我们之前所说的我们实现什么程序就使用什么在这里就等同于我们在哪个类上标识了Component注解哪个类就会是一个BeanSpring就会使用它注入Boy的属性Car中 所以当我们给GeelyCar标识Component注解时Boy开的车就是GeelyCar当我们给HongQiCar标识Component注解时Boy开的车就是HongQiCar 当然我们不可以在GeelyCar和HongQiCar上同时标识Component注解因为这样Spring就不知道用哪个Car进行注入了——Spring也有选择困难症or 一boy不能开俩车 使用Spring启动程序 java 复制代码// 告诉Spring从哪个包下扫描Bean不写就是当前包路径ComponentScan(basePackages com.my.spring.test.demo)public class Main { public static void main(String[] args) { // 将Main(配置信息)传入到ApplicationContext(IoC容器)中 ApplicationContext context new AnnotationConfigApplicationContext(Main.class); // 从(IoC容器)中获取到我们的boy Boy boy (Boy) context.getBean(boy); // 开车 boy.driver(); }}这里就可以把我们刚刚介绍Spring的知识进行解读了 把具有ComponentScan注解(配置信息)的Main类传给AnnotationConfigApplicationContext(IoC容器)进行初始化就等于IoC容器通过获取配置信息进行实例化、管理和组装Bean。 而如何进行依赖注入则是在IoC容器内部完成的这也是本文要讨论的重点 思考 我们通过一个改造案例完整的认识了Spring的基本功能也对之前的概念有了一个具象化的体验而我们还并不知道Spring的依赖注入这一内部动作是如何完成的所谓知其然更要知其所以然结合我们的现有知识以及对Spring的理解大胆猜想推测一下吧(这是很重要的能力哦) 其实猜测就是指如果让我们自己实现我们会如何实现这个过程 首先我们要清楚我们需要做的事情是什么扫描指定包下面的类进行实例化并根据依赖关系组合好。 步骤分解 扫描指定包下面的类 - 如果这个类标识了Component注解(是个Bean) - 把这个类的信息存起来 进行实例化 - 遍历存好的类信息 - 通过反射把这些类进行实例化 根据依赖关系组合 - 解析类信息 - 判断类中是否有需要进行依赖注入的字段 - 对字段进行注入 方案实现 我们现在已经有了一个看起来像是那么一回事的解决方案现在就尝试把这个方案实现出来 定义注解 首先我们需要定义出需要用到的注解ComponentScan,Component,Autowired java复制代码Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) public interface ComponentScan {String basePackages() default ; } java复制代码Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) public interface Component {String value() default ; } java 复制代码Target(ElementType.FIELD)Retention(RetentionPolicy.RUNTIME)public interface Autowired {}扫描指定包下面的类 扫描指定包下的所有类听起来好像一时摸不着头脑其实它等同于另一个问题如何遍历文件目录 那么存放类信息应该用什么呢我们看看上面例子中getBean的方法是不是像Map中的通过key获取value而Map中还有很多实现但线程安全的却只有一个那就是ConcurrentHashMap(别跟我说HashTable) 定义存放类信息的map java 复制代码private final MapString, Class? classMap new ConcurrentHashMap(16);具体流程下面同样附上代码实现 代码实现可以与流程图结合观看 扫描类信息 java复制代码private void scan(Class? configClass) {// 解析配置类获取到扫描包路径String basePackages this.getBasePackages(configClass);// 使用扫描包路径进行文件遍历操作this.doScan(basePackages); } java复制代码private String getBasePackages(Class? configClass) {// 从ComponentScan注解中获取扫描包路径ComponentScan componentScan configClass.getAnnotation(ComponentScan.class);return componentScan.basePackages(); } java复制代码private void doScan(String basePackages) {// 获取资源信息URI resource this.getResource(basePackages);File dir new File(resource.getPath());for (File file : dir.listFiles()) {if (file.isDirectory()) {// 递归扫描doScan(basePackages . file.getName());}else {// com.my.spring.example . Boy.class - com.my.spring.example.BoyString className basePackages . file.getName().replace(.class, );// 将class存放到classMap中this.registerClass(className);}} } java复制代码private void registerClass(String className){try {// 加载类信息Class? clazz classLoader.loadClass(className);// 判断是否标识Component注解if(clazz.isAnnotationPresent(Component.class)){// 生成beanName com.my.spring.example.Boy - boyString beanName this.generateBeanName(clazz);// car: com.my.spring.example.CarclassMap.put(beanName, clazz);}} catch (ClassNotFoundException ignore) {} }实例化 现在已经把所有适合的类都解析好了接下来就是实例化的过程了 定义存放Bean的Map java 复制代码private final MapString, Object beanMap new ConcurrentHashMap(16);具体流程下面同样给出代码实现 代码实现可以与流程图结合观看 遍历classMap进行实例化Bean java复制代码public void instantiateBean() {for (String beanName : classMap.keySet()) {getBean(beanName);} } java复制代码public Object getBean(String beanName){// 先从缓存中获取Object bean beanMap.get(beanName);if(bean ! null){return bean;}return this.createBean(beanName); } java复制代码private Object createBean(String beanName){Class? clazz classMap.get(beanName);try {// 创建beanObject bean this.doCreateBean(clazz);// 将bean存到容器中beanMap.put(beanName, bean);return bean;} catch (IllegalAccessException e) {throw new RuntimeException(e);} } java复制代码private Object doCreateBean(Class? clazz) throws IllegalAccessException {// 实例化beanObject bean this.newInstance(clazz);// 填充字段将字段设值this.populateBean(bean, clazz);return bean; } java 复制代码private Object newInstance(Class? clazz){ try { // 这里只支持默认构造器 return clazz.getDeclaredConstructor().newInstance(); } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { throw new RuntimeException(e); }} java 复制代码private void populateBean(Object bean, Class? clazz) throws IllegalAccessException { // 解析class信息判断类中是否有需要进行依赖注入的字段 final Field[] fields clazz.getDeclaredFields(); for (Field field : fields) { Autowired autowired field.getAnnotation(Autowired.class); if(autowired ! null){ // 获取bean Object value this.resolveBean(field.getType()); field.setAccessible(true); field.set(bean, value); } }} java复制代码private Object resolveBean(Class? clazz){// 先判断clazz是否为一个接口是则判断classMap中是否存在子类if(clazz.isInterface()){// 暂时只支持classMap只有一个子类的情况for (Map.EntryString, Class? entry : classMap.entrySet()) {if (clazz.isAssignableFrom(entry.getValue())) {return getBean(entry.getValue());}}throw new RuntimeException(找不到可以进行依赖注入的bean);}else {return getBean(clazz);} } java复制代码public Object getBean(Class? clazz){// 生成bean的名称String beanName this.generateBeanName(clazz);// 此处对应最开始的getBean方法return this.getBean(beanName); }组合 两个核心方法已经写好了接下把它们组合起来我把它们实现在自定义的ApplicationContext类中构造方法如下 java复制代码public ApplicationContext(Class? configClass) {// 1.扫描配置信息中指定包下的类this.scan(configClass);// 2.实例化扫描到的类this.instantiateBean(); }UML类图 测试 代码结构与案例相同这里展示一下我们自己的Spring是否可以正常运行 运行正常中国人不骗中国人 源码会在文末给出 回顾 现在我们已经根据设想的方案进行了实现运行的情况也达到了预期的效果。但如果仔细研究一下再结合我们平常使用Spring的场景就会发现这一份代码的不少问题 1、无法支持构造器注入当然也没有支持方法注入这是属于功能上的缺失。 2、加载类信息的问题加载类时我们使用的是classLoader.loadClass的方式虽然这避免了类的初始化(可千万别用Class.forName的方式)但还是不可避免的把类元信息加载到了元空间中当我们扫描包下有不需要的类时这就浪费了我们的内存。 3、无法解决bean之间的循环依赖比如有一个A对象依赖了B对象 B对象又依赖了A对象这个时候我们再来看看代码逻辑就会发现此时会陷入死循环。 4、扩展性很差我们把所有的功能都写在一个类里当想要完善功能(比如以上3个问题)时就需要频繁修改这个类这个类也会变得越来越臃肿别说迭代新功能维护都会令人头疼。 优化方案 对于前三个问题都类似于功能上的问题功能嘛改一改就好了。 我们需要着重关注的是第四个问题一款框架想要变得优秀那么它的迭代能力一定要好这样功能才能变得丰富而迭代能力的影响因素有很多其中之一就是它的扩展性。 那么应该如何提高我们的方案的扩展性呢六大设计原则给了我们很好的指导作用。 在方案中ApplicationContext做了很多事情 主要可以分为两大块 1、扫描指定包下的类 2、实例化Bean 借助单一职责原则的思想一个类只做一种事一个方法只做一件事。 我们把扫描指定包下的类这件事单独使用一个处理器进行处理因为扫描配置是从配置类而来那我们就叫他配置类处理器ConfigurationCalssProcessor 实例化Bean这件事情也同样如此实例化Bean又分为了两件事实例化和依赖注入 实例化Bean就是相当于一个生产Bean的过程我们就把这件事使用一个工厂类进行处理它就叫做BeanFactory既然是在生产Bean那就需要原料(Class)所以我们把classMap和beanMap都定义到这里 而依赖注入的过程其实就是在处理Autowired注解那它就叫做: AutowiredAnnotationBeanProcessor 我们还在知道在Spring中不仅仅只有这种使用方式还有xmlmvcSpringBoot的方式所以我们将ApplicationContext进行抽象只实现主干流程原来的注解方式交由AnnotationApplicationContext实现。 借助依赖倒置原则程序应当依赖于抽象 在未来类信息不仅仅可以从类信息来也可以从配置文件而来所以我们将ConfigurationCalssProcessor抽象 而依赖注入的方式不一定非得是用Autowried注解标识也可以是别的注解标识比如Resource所以我们将AutowiredAnnotationBeanProcessor抽象 Bean的类型也可以有很多可以是单例的可以使多例的也可以是个工厂Bean所以我们将BeanFactory抽象 现在我们借助两大设计原则对我们的方案进行了优化相比于之前可谓是”脱胎换骨“。 Spring的设计 在上一步我们实现了自己的方案并基于一些设想进行了扩展性优化现在我们就来认识一下实际上Spring的设计 那么在Spring中又是由哪些角色构成的呢 1、Bean: Spring作为一个IoC容器最重要的当然是Bean咯 2、BeanFactory: 生产与管理Bean的工厂 3、BeanDefinition: Bean的定义也就是我们方案中的ClassSpring对它进行了封装 4、BeanDefinitionRegistry: 类似于Bean与BeanFactory的关系BeanDefinitionRegistry用于管理BeanDefinition 5、BeanDefinitionRegistryPostProcessor: 用于在解析配置类时的处理器类似于我们方案中的ClassProcessor 6、BeanFactoryPostProcessor: BeanDefinitionRegistryPostProcessor父类让我们可以再解析配置类之后进行后置处理 7、BeanPostProcessor: Bean的后置处理器用于在生产Bean的过程中进行一些处理比如依赖注入类似我们的AutowiredAnnotationBeanProcessor 8、ApplicationContext: 如果说以上的角色都是在工厂中生产Bean的工人那么ApplicationContext就是我们Spring的门面ApplicationContext与BeanFactory是一种组合的关系所以它完全扩展了BeanFactory的功能并在其基础上添加了更多特定于企业的功能比如我们熟知的ApplicationListener(事件监听器) 以上说的类似其实有一些本末倒置了因为实际上应该是我们方案中的实现类似于Spring中的实现这样说只是为了让大家更好的理解 我们在经历了自己方案的设计与优化后对这些角色其实是非常容易理解的 接下来我们就一个一个的详细了解一下 BeanFactory BeanFactory是Spring中的一个顶级接口它定义了获取Bean的方式Spring中还有另一个接口叫SingletonBeanRegistry它定义的是操作单例Bean的方式这里我将这两个放在一起进行介绍因为它们大体相同SingletonBeanRegistry的注释上也写了可以与BeanFactory接口一起实现方便统一管理。 BeanFactory 1、ListableBeanFactory接口定义了获取Bean/BeanDefinition列表相关的方法如getBeansOfType(Class type) 2、AutowireCapableBeanFactory接口定义了Bean生命周期相关的方法如创建bean, 依赖注入初始化 3、AbstractBeanFactory抽象类基本上实现了所有有关Bean操作的方法定义了Bean生命周期相关的抽象方法 4、AbstractAutowireCapableBeanFactory抽象类继承了AbstractBeanFactory实现了Bean生命周期相关的内容虽然是个抽象类但它没有抽象方法 5、DefaultListableBeanFactory继承与实现以上所有类和接口是为Spring中最底层的BeanFactory, 自身实现了ListableBeanFactory接口 6、ApplicationContext也是一个接口我们会在下面有专门对它的介绍 SingletonBeanRegistry 1、DefaultSingletonBeanRegistry 定义了Bean的缓存池类似于我们的BeanMap实现了有关单例的操作比如getSingleton(面试常问的三级缓存就在这里) 2、FactoryBeanRegistrySupport提供了对FactoryBean的支持比如从FactoryBean中获取Bean BeanDefinition BeanDefinition其实也是个接口(想不到吧)这里定义了许多和类信息相关的操作方法方便在生产Bean的时候直接使用比如getBeanClassName 它的大概结构如下(这里举例RootBeanDefinition子类) 里面的各种属性想必大家也绝不陌生 同样的它也有许多实现类 1、AnnotatedGenericBeanDefinition解析配置类与解析Import注解带入的类时就会使用它进行封装 2、ScannedGenericBeanDefinition封装通过ComponentScan扫描包所得到的类信息 3、ConfigurationClassBeanDefinition封装通过Bean注解所得到的类信息 4、RootBeanDefinitionConfigurationClassBeanDefinition父类一般在Spring内部使用将其他的BeanDefition转化成该类 BeanDefinitionRegistry 定义了与BeanDefiniton相关的操作如registerBeanDefinitiongetBeanDefinition在BeanFactory中实现类就是DefaultListableBeanFactory BeanDefinitionRegistryPostProcessor 插话讲到这里有没有发现Spring的命名极其规范Spring团队曾言Spring中的类名都是反复推敲才确认的真是名副其实呀所以看Spring源码真的是一件很舒服的事情看看类名方法名就能猜出它们的功能了。 该接口只定义了一个功能处理BeanDefinitonRegistry也就是解析配置类中的Import、Component、ComponentScan等注解进行相应的处理处理完毕后将这些类注册成对应的BeanDefinition 在Spring内部中只有一个实现ConfigurationClassPostProcessor BeanFactoryPostProcessor 所谓BeanFactory的后置处理器它定义了在解析完配置类后可以调用的处理逻辑类似于一个插槽如果我们想在配置类解析完后做点什么就可以实现该接口。 在Spring内部中同样只有ConfigurationClassPostProcessor实现了它用于专门处理加了Configuration注解的类 这里串场一个小问题如知以下代码 java复制代码Configuraiton public class MyConfiguration{Beanpublic Car car(){return new Car(wheel());}Beanpublic Wheel wheel(){return new Wheel();} }问Wheel对象在Spring启动时被new了几次为什么 BeanPostProcessor 江湖翻译Bean的后置处理器 该后置处理器贯穿了Bean的生命周期整个过程在Bean的创建过程中一共被调用了9次至于哪9次我们下次再来探究以下介绍它的实现类以及作用 1、AutowiredAnnotationBeanPostProcessor用于推断构造器进行实例化以及处理Autowired和Value注解 2、CommonAnnotationBeanPostProcessor处理Java规范中的注解如Resource、PostConstruct 3、ApplicationListenerDetector: 在Bean的初始化后使用将实现了ApplicationListener接口的bean添加到事件监听器列表中 4、ApplicationContextAwareProcessor用于回调实现了Aware接口的Bean 5、ImportAwareBeanPostProcessor: 用于回调实现了ImportAware接口的Bean ApplicationContext ApplicationContext作为Spring的核心以门面模式隔离了BeanFactory以模板方法模式定义了Spring启动流程的骨架又以策略模式调用了各式各样的Processor…实在是错综复杂又精妙绝伦! 它的实现类如下 1、ConfigurableApplicationContext接口定义了配置与生命周期相关操作如refresh 2、AbstractApplicationContext: 抽象类实现了refresh方法refresh方法作为Spring核心中的核心,可以说整个Spring皆在refresh之中所有子类都通过refresh方法启动在调用该方法之后将实例化所有单例 3、AnnotationConfigApplicationContext: 在启动时使用相关的注解读取器与扫描器往Spring容器中注册需要用的处理器而后在refresh方法在被主流程调用即可 4、AnnotationConfigWebApplicationContext实现loadBeanDefinitions方法以期在refresh流程中被调用从而加载BeanDefintion 5、ClassPathXmlApplicationContext: 同上 从子类的情况可以看出子类的不同之处在于如何加载BeanDefiniton, AnnotationConfigApplicationContext是通过配置类处理器(ConfigurationClassPostProcessor)加载的而AnnotationConfigWebApplicationContext与ClassPathXmlApplicationContext则是通过自己实现loadBeanDefinitions方法其他流程则完全一致 Spring的流程 以上我们已经清楚了Spring中的主要角色以及作用现在我们尝试把它们组合起来构建一个Spring的启动流程 同样以我们常用的AnnotationConfigApplicationContext为例 图中只画出了Spring中的部分大概流程详细内容我们会在后面的章节展开 小结 所谓万事开头难本文初衷就是能让大家以由浅入深的方式认识Spring初步建立Spring的认知体系明白Spring的内部架构对Spring的认知不再浮于表面。 现在头已经开了相信后面内容的学习也将水到渠来。 本篇文章既讲是Spring的架构设计也希望能成为我们以后复习Spring整体内容时使用的手册。 最后看完文章之后相信对以下面试常问的问题回答起来也是轻而易举 1、什么是BeanDefinition 2、BeanFactory与ApplicationContext的关系 3、后置处理器的分类与作用 4、Spring的主要流程是怎么样的 如果小伙伴觉得没办法很好回答上来的话就再看看文章或者在评论区留下自己的见解吧
http://www.pierceye.com/news/397641/

相关文章:

  • 网站给假冒伪劣产品做推广鞍山网站制作一般需要多少钱
  • 番禺网站开发哪里好ppt模板免费下载完整版免费简约
  • 哪个公司做企业网站好济南网站优化推广公司电话
  • 深圳网站建设外包公司网站流量提供商
  • 网站建设优化服务信息wordpress下载类插件
  • 深圳做网站google推广百度优化是什么
  • 网站开发技术服务费分享经济网站怎么建设
  • 免费seo网站推广在线观看360免费wifi创建失败
  • 服装网站开发嵌入式硬件开发
  • 上海建设厅网站那些网站可以做自媒体
  • 如何查看一个网站流量网店美工课程心得体会
  • 邯郸的网站建设无锡做网站品牌公司
  • 汇编做网站门户网站建设 知乎
  • 教育云平台网站建设云南小程序定制开发
  • 企业自助建站策划方案横沥网站设计
  • 网站开发搜索功能怎么实现中小网站建设都有哪些方案
  • 学科网站建设网页制作和网页制作
  • 公司网站模板大全网站文章编辑
  • 旅游网站建设的总结wordpress多域名移动主题
  • 深圳做网站推荐哪家公司好附近广告公司联系电话
  • 网站建设和网站优化哪个更重要提供邯郸网站建设
  • 做网站一般把宽度做多少合肥优化
  • 石家庄做网站公司汉狮价格猴痘的治疗方法
  • 自己有网站 做app吗深圳罗湖企业网站推广
  • 廊坊建设局网站6阿里云虚拟主机网站
  • 设计一个电商网站西安seo盐城
  • 上海网站公司建设网页设计网站欣赏
  • 平台网站如何做推广1280的界面网站做多宽
  • 男男做爰视频网站微信扫码点餐小程序怎么做
  • 哈尔滨做网站的价格如何利用wordpress搭建一个发卡网