读书笔记-设计模式和spring

1、开闭原则(Open-Closed Principle,OCP)是指一个软件实体(如类、模块和函数)应该对扩展开放,对修改关闭。所谓的开闭,也正是对扩展和修改两个行为的一个原则。开闭原则的核心思想就是面向抽象编程


2、依赖倒置原则(Dependence Inversion Principle,DIP)是指设计代码结构时,高层模块不应该依赖低层模块,二者都应该依赖其抽象。抽象不应该依赖细节,细节应该依赖抽象


3、单一职责(Simple Responsibility Pinciple,SRP)是指不要存在多于一个导致类变更的原因。假设我们有一个类负责两个职责,一旦发生需求变更,修改其中一个职责的逻辑代码,有可能导致另一个职责的功能发生故障


4、接口隔离原则(Interface Segregation Principle,ISP)是指用多个专门的接口,而不使用单一的总接口,客户端不应该依赖它不需要的接口。这个原则指导我们在设计接口时应当注意以下几点:
(1)一个类对另一个类的依赖应该建立在最小的接口之上。
(2)建立单一接口,不要建立庞大臃肿的接口。
(3)尽量细化接口,接口中的方法尽量少(不是越少越好,一定要适度)。

5、迪米特原则(Law of Demeter LoD)是指一个对象应该对其他对象保持最少的了解,又叫最少知道原则(Least Knowledge Principle,LKP),尽量降低类与类之间的耦合度。迪米特原则主要强调:只和朋友交流,不和陌生人说话。出现在成员变量、方法的输入、输出参数中的类都可以称为成员朋友类,而出现在方法体内部的类不属于朋友类
6、里氏替换原则(Liskov Substitution Principle,LSP)是指如果对每一个类型为T1的对象o1,都有类型为T2的对象O2,使得以T1定义的所有程序P在所有的对象O1都替换成O2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。
这个定义看上去还是比较抽象的,我们重新理解一下。可以理解为一个软件实体如果适用于一个父类,那么一定适用于其子类,所有引用父类的地方必须能透明地使用其子类的对象,子类对象能够替换父类对象,而程序逻辑不变。根据这个理解,引申含义为:子类可以扩展父类的功能,但不能改变父类原有的功能。
(1)子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
(2)子类可以增加自己特有的方法。
(3)当子类的方法重载父类的方法时,方法的前置条件(即方法的输入/入参)要比父类方法的输入参数更宽松。
(4)当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的输出/返回值)要比父类更严格或与父类一样


7、合成复用原则(Composite/Aggregate Reuse Principle,CARP)是指尽量使用对象组合(has-a)/聚合(contanis-a)而不是继承关系达到软件复用的目的。可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少。
继承叫作白箱复用,相当于把所有的实现细节暴露给子类。组合/聚合称为黑箱复用,我们是无法获取到类以外的对象的实现细节的。虽然我们要根据具体的业务场景来做代码设计,但也需要遵循OOP模型。
继承叫作白箱复用,相当于把所有的实现细节暴露给子类。组合/聚合称为黑箱复用

8、Spring框架中大量使用了抽象工厂,applicationcontext类


9、单例类:饿汉式双重检查锁的单例模式->静态内部类->要避免反射方式调用多次创建实例,
序列化会破坏单例模式->枚举式单例模式在静态代码块中就给INSTANCE进行了赋值,是饿汉式单例模式的实现
枚举类型其实通过类名和类对象类找到一个唯一的枚举对象。因此,枚举对象不可能被类加载器加载多次,枚举式单例模式也是EffectiveJava书中推荐的一种单例模式实现写法;Spring中采用容器式单例模式;单例模式为了达到线程安全的目的,会给方法上锁,以时间换空间。ThreadLocal 将所有的对象全部放在ThreadLocalMap中,为每个线程都提供一个对象,实际上是以空间换时间来实现线程隔离的


10、原型模式(Prototype Pattern)是指原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
原型模式主要适用于以下场景:
(1)类初始化消耗资源较多。
(2)使用new生成一个对象需要非常烦琐的过程(数据准备、访问权限等)。
(3)构造函数比较复杂。
(4)在循环体中产生大量对象。
一个标准的原型模式代码应该是这样设计的,先创建原型Prototype接口,在创建原型具体类,在创建client端
浅克隆只是完整复制了值类型数据,没有赋值引用对象,java中的原型类的最终会实现最顶层的cloneable和serializable类
如果我们克隆的目标对象是单例对象,那么意味着深克隆会破坏单例模式。实际上防止克隆破坏单例模式的解决思路非常简单,禁止深克隆便可。要么我们的单例类不实现 Cloneable接口,要么我们重写clone()方法,在clone()方法中返回单例对象即可
常用的ArrayList实现了Cloneable接口

10、结构型设计模式:代理模式(Proxy Pattern)的定义也非常简单,是指为其他对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用,使用代理模式主要有两个目的:一是保护目标对象,二是增强目标对象。subject是顶层接口,RealSubject是真实对象(被代理对象),Proxy是代理对象,代理对象持有被代理对象的引用,客户端调用代理对象的方法,同时也调用被代理对象的方法,但是会在代理对象前后增加一些处理代码。在代码中,一般代理会被理解为代码增强,实际上就是在原代码逻辑前后增加一些代码逻辑,而使调用者无感知。代理模式属于结构型模式,分为静态代理和动态代理
在分布式业务场景中,通常会对数据库进行分库分表,分库分表之后使用 Java操作时就可能需要配置多个数据源,我们通过设置数据源路由来动态切换数据源
动态代理和静态代理的基本思路是一致的,只不过动态代理功能更加强大,随着业务的扩展适应性更强。如果还以找对象为例,那么使用动态代理相当于能够适应复杂的业务场景
代理类最顶层会实现invocationhandler类
JDK动态代理采用字节重组,重新生成对象来替代原始对象,以达到动态代理的目的。JDK动态代理生成对象的步骤如下:
(1)获取被代理对象的引用,并且获取它的所有接口,反射获取。
(2)JDK动态代理类重新生成一个新的类,同时新的类要实现被代理类实现的所有接口。
(3)动态生成Java代码,新加的业务逻辑方法由一定的逻辑代码调用(在代码中体现)。
(4)编译新生成的Java代码.class文件。
(5)重新加载到JVM中运行。
JDK中有一个规范,在ClassPath下只要是$开头的.class文件,一般都是自动生成的。
代理对象调用 this.findLove()方法→调用拦截器→methodProxy.invokeSuper→CGLIB$findLove$0→被代理对象findLove()方法
CGLib代理执行代理方法的效率之所以比JDK的高,是因为CGlib采用了FastClass机制,它的原理简单来说就是:为代理类和被代理类各生成一个类,这个类会为代理类或被代理类的方法分配一个index(int类型);这个index当作一个入参,FastClass就可以直接定位要调用的方法并直接进行调用,省去了反射调用,所以调用效率比JDK代理通过反射调用高
CGLib和JDK动态代理对比
(1)JDK动态代理实现了被代理对象的接口,CGLib代理继承了被代理对象。
(2)JDK动态代理和CGLib代理都在运行期生成字节码,JDK动态代理直接写Class字节码,CGLib代理使用ASM框架写Class字节码,CGlib代理实现更复杂,生成代理类比JDK动态代理效率低。
(3)JDK动态代理调用代理方法是通过反射机制调用的,CGLib代理是通过FastClass机制直接调用方法的,CGLib代理的执行效率更高
Spring中代理模式:
在getObject()方法中,主要调用getSingletonInstance()和newPrototypeInstance()。在Spring的配置中如果不做任何设置,那么Spring代理生成的Bean都是单例对象。如果修改scope,则每次创建一个新的原型对象
(1)当Bean有实现接口时,Spring就会用JDK动态代理。
(2)当Bean没有实现接口时,Spring会选择CGLib代理。
(3)Spring可以通过配置强制使用CGLib代理,只需在Spring的配置文件中加入相关代码
静态代理和动态代理的本质区别
(1)静态代理只能通过手动完成代理操作,如果被代理类增加了新的方法,代理类需要同步增加,违背开闭原则。
(2)动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开闭原则。
若动态代理要对目标类的增强逻辑进行扩展,结合策略模式,只需要新增策略类便可完成,无须修改代理类的代码
代理模式具有以下优点:
(1)代理模式能将代理对象与真实被调用目标对象分离。
(2)在一定程度上降低了系统的耦合性,扩展性好。
(3)可以起到保护目标对象的作用。
(4)可以增强目标对象的功能。
当然,代理模式也有缺点:
(1)代理模式会造成系统设计中类的数量增加。
(2)在客户端和目标对象中增加一个代理对象,会导致请求处理速度变慢。
(3)增加了系统的复杂度。


11、委派模式(Delegate Pattern)不属于GoF 23种设计模式。委派模式的基本作用就是负责任务的调用和分配,跟代理模式很像,可以看作一种特殊情况下的静态的全权代理,但是代理模式注重过程,而委派模式注重结果
委派模式在Spring中应用得非常多,大家常用的DispatcherServlet就用到了委派模式
代理模式注重的是过程,委派模式注重的是结果
策略模式注重可扩展性(外部扩展性),委派模式注重内部的灵活性和可复用性
委派模式的核心是分发、调度、派遣,委派模式是静态代理和策略模式的一种特殊组合
在Spring源码中,以Delegate结尾的地方都实现了委派模式,例如BeanDefinitionParserDelegate根据不同类型委派不同的逻辑解析BeanDefinition


12、策略模式(Strategy Pattern)是指定义了算法家族并分别封装起来,让它们之间可以互相替换,此模式使得算法的变化不会影响使用算法的用户
策略模式的应用场景如下。
(1)系统中有很多类,而它们的区别仅仅在于行为不同。
(2)一个系统需要动态地在几种算法中选择一种。
比较常用的比较器—Comparator接口,大家常用的compare()方法就是一个策略模式的抽象实现
Spring源码中Resource接口和DispatcherServlet类,Spring 的初始化也采用了策略模式,即不同类型的类采用不同的初始化策略。有一个InstantiationStrategy接口,
CglibSubclassingInstantiationStrategy类继承了SimpleInstantiationStrategy类,说明在实际应用中多种策略之间可以继承使用
策略模式的优点如下:
(1)策略模式符合开闭原则。
(2)策略模式可避免使用多重条件语句,如if...else语句、switch语句。
(3)使用策略模式可以提高算法的保密性和安全性。
策略模式的缺点如下:
(1)客户端必须知道所有的策略,并且自行决定使用哪一个策略类。
(2)代码中会产生非常多的策略类,增加了代码的维护难度。


13、行为型设计模式:模板模式又叫模板方法模式(Template Method Pattern),是指定义一个算法的骨架,并允许子类为一个或者多个步骤提供实现。模板模式使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤
1)一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。
(2)各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复。
创建一个模板类 JdbcTemplate,封装所有的 JDBC 操作。以查询为例,每次查询的表不同,返回的数据结构也就不一样。我们针对不同的数据,都要将其封装成不同的实体对象。JDK中的AbstractList类,get()是一个抽象方法,交给子类来实现,大家所熟知的ArrayList就是AbstractList的子类。同理,有AbstractList就有AbstractSet和AbstractMap,另外HttpServlet有三个方法:service()、doGet()和doPost(),都是模板方法的抽象实现。在MyBatis框架中也有一些经典的应用,我们来一下BaseExecutor类。它是一个基础的SQL执行类,实现了大部分SQL的执行逻辑,然后把几个方法交给子类定制化完成。
模板模式的优点如下:
(1)利用模板模式将相同处理逻辑的代码放到抽象父类中,可以提高代码的复用性。
(2)将不同的代码放到不同的子类中,通过对子类的扩展增加新的行为,可以提高代码的扩展性。
(3)把不变的行为写在父类中,去除子类的重复代码,提供了一个很好的代码复用平台,符合开闭原则。
模板模式的缺点如下:
(1)每个抽象类都需要一个子类来实现,导致了类的数量增加。
(2)类数量的增加间接地增加了系统的复杂性。
(3)因为继承关系自身的缺点,如果父类添加新的抽象方法,所有子类都要改一遍。
模板模式比较简单,相信“小伙伴们”肯定能学会,也肯定能理解好!只要勤加练习,多结合业务场景思考问题,就能够把模板模式运用好

14、适配器模式(Adapter Pattern)是指将一个类的接口转换成用户期望的另一个接口,使原本接口不兼容的类可以一起工作,属于结构型设计模式。
适配器模式适用于以下几种业务场景:
(1)已经存在的类的方法和需求不匹配(方法结果相同或相似)的情况。
(2)适配器模式不是软件初始阶段考虑的设计模式,是随着软件的发展,由于不同产品、不同厂家造成功能类似而接口不同的问题的解决方案,有点亡羊补牢的感觉。
适配器模式跟策略模式好像区别不大?在这里要强调一下,适配器模式主要解决的是功能兼容问题,单场景适配时大家可能不会和策略模式对比,但多场景适配时大家就会产生联想和混淆。不知道大家有没有发现一个细节,前面给每个适配器都加上了一个 support()方法,用来判断是否兼容。support()方法的参数也是 Object 类型的,而support()方法来自接口。适配器的实现并不依赖接口,我们完全可以将LoginAdapter接口去掉,加上它只是为了代码规范。Spring AOP中的AdvisorAdapter类,它有三个实现类:MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter 和 ThrowsAdviceAdapter
适配器模式的优点如下:
(1)能提高类的透明性和复用性,现有的类会被复用但不需要改变。
(2)目标类和适配器类解耦,可以提高程序的扩展性。
(3)在很多业务场景中符合开闭原则。
适配器模式的缺点如下:
(1)在适配器代码编写过程中需要进行全面考虑,可能会增加系统的复杂性。
(2)增加了代码的阅读难度,降低了代码的可读性,过多使用适配器会使系统的代码变得凌乱。
15、装饰者模式(Decorator Pattern)是指在不改变原有对象的基础上,将功能附加到对象上,提供了比继承更有弹性的方案(扩展原有对象的功能),属于结构型模式
饰者模式适用于以下场景:
(1)扩展一个类的功能或给一个类添加附加职责。
(2)动态给一个对象添加功能,这些功能可以再动态地撤销。
为了实现新功能与老功能的兼容,创建了一个新的类继承已有的类,实现功能的扩展,遵循开闭原则
装饰者模式最本质的特征是将原有类的附加功能抽离出来,简化原有类的逻辑。通过案例可以总结出,其实抽象的装饰者是可有可无的,具体可以根据业务模型来选择
装饰者模式和适配器模式都是包装模式(Wrapper Pattern),装饰者模式也是一种特殊的代理模式
JDK 中体现最明显的类就是 I/O 相关的类,如BufferedReader、InputStream、OutputStream
装饰者模式的优点如下:
(1)装饰者模式是继承的有力补充,且比继承灵活,可以在不改变原有对象的情况下动态地给一个对象扩展功能,即插即用。
(2)使用不同的装饰类及这些装饰类的排列组合,可以实现不同的效果。
(3)装饰者模式完全符合开闭原则。
装饰者模式的缺点如下:
(1)会出现更多的代码、更多的类,增加程序的复杂性。
(2)动态装饰时,多层装饰会更复杂。


16、观察者模式(Observer Pattern)定义了对象之间的一对多依赖,让多个观察者对象同时监听一个主体对象,当主体对象发生变化时,它的所有依赖者(观察者)都会收到通知并更新,属于行为型模式。观察者模式有时也叫作发布订阅模式
java.awt.Event就是观察者模式;Spring中的ContextLoaderListener类实现了ServletContextListener接口,ServletContextListener接口又继承了 EventListener 接口。
观察者模式的优点如下:
(1)在观察者和被观察者之间建立了一个抽象的耦合。
(2)观察者模式支持广播通信。
观察者模式的缺点如下:
(1)观察者之间有过多的细节依赖、时间消耗多,程序的复杂性更高。
(2)使用不当会出现循环调用。


16、设计模式之间的关系
1.单例模式和工厂模式
在实际业务代码中,通常会把工厂类设计为单例模式。
2.策略模式和工厂模式
(1)工厂模式包含工厂方法模式和抽象工厂模式,是创建型模式,策略模式属于行为型模式。
(2)工厂模式的主要目的是封装好创建逻辑,策略模式接收工厂创建好的对象,从而实现不同的行为。
3.策略模式和委派模式
(1)策略模式是委派模式内部的一种实现形式,策略模式关注结果是否能相互替代。
(2)委派模式更关注分发和调度的过程。
4.模板方法模式和工厂方法模式
工厂方法模式是模板方法模式的一种特殊实现
5.模板方法模式和策略模式
(1)模板方法模式和策略模式都有封装算法。
(2)策略模式使不同算法可以相互替换,且不影响客户端应用层的使用。
(3)模板方法模式针对定义一个算法的流程,将一些有细微差异的部分交给子类实现。
(4)模板方法模式不能改变算法流程,策略模式可以改变算法流程且可替换。策略模式通常用来代替if...else等条件分支语句
6.装饰者模式和代理模式
(1)装饰者模式的关注点在于给对象动态添加方法,而代理模式更加注重控制对象的访问
(2)代理模式通常会在代理类中创建被代理对象的实例,而装饰者模式通常会把被装饰者作为构造参数
7.装饰者模式和适配器模式
(1)装饰者模式和适配器模式都属于包装器模式(Wrapper Pattern)。
(2)装饰者模式可以实现与被装饰者相同的接口,或者继承被装饰者作为它的子类,而适配器和被适配者可以实现不同的接口。
8.适配器模式和静态代理模式
适配器模式可以结合静态代理模式来实现,保存被适配对象的引用,但不是唯一的实现方式。
9.适配器模式和策略模式
在业务复杂的情况下,可利用策略模式优化适配器模式。


17、Spring框架除了帮我们管理对象及其依赖关系,还提供通用日志记录、性能统计、安全控制、异常处理等面向切面的能力,能帮我们管理最头疼的数据库事务,它本身提供了一套简单的JDBC访问实现,可与第三方数据访问框架集成(如 Hibernate、JPA),与各种 Java EE 技术整合(如Java Mail、任务调度等),提供一套自己的Web层框架Spring MVC,还能非常简单地与第三方Web框架集成。
Spring立志于全方位地简化Java开发。对此,它主要采取了4个关键策略:
(1)基于POJO的轻量级和最小侵入性编程。
(2)通过依赖注入和面向接口实现松耦合。
(3)基于切面和惯性进行声明式编程。
(4)通过切面和模板减少样板式代码。
以上策略主要是通过面向Bean(BOP)、依赖注入(DI)及面向切面(AOP)这三种方式来实现的。
Bean对于Spring的意义就像Object对于OOP的意义一样,Spring中没有Bean也就没有Spring存在的意义。Spring IoC容器通过配置文件或者注解的方式来管理对象之间的依赖关系。
eanFactory底层支持两个对象模型。
(1)单例模型:提供了具有特定名称的全局共享实例对象,可以在查询时对其进行检索。Singleton是默认的、也是最常用的单例模型。
(2)原型模型:确保每次检索都会创建单独的实例对象。在每个用户都需要自己的对象时,采用原型模型。
BeanFactory(Bean工厂)是Spring作为IoC容器的基础。IoC则将处理事情的责任从应用程序代码转移到框架。
OP即面向切面编程,是一种编程思想,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP的核心构造是切面,它将那些影响多个类的行为封装到可重用的模块中。
AOP 和 IoC 是补充性的技术,它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型的面向对象开发方式中,可能要将日志记录语句放在所有方法和Java类中才能实现日志功能。在AOP方式中,可以反过来将日志服务模块化,并以声明的方式将它们应用到需要日志的组件上。当然,优势就是Java类不需要知道日志服务的存在,也不需要考虑相关的代码。所以,用Spring AOP编写的应用程序代码是松耦合的。
AOP编程的常用场景有:Authentication(权限认证)、Auto Caching(自动缓存)、Error Handling (错误处理)、Debugging(调试)、Logging(日志)、Transaction(事务)等。
ApplicationContext是Spring提供的一个高级的IoC容器,它除了能够提供IoC容器的基本功能,还为用户提供了以下附加服务。
(1)支持信息源,可以实现国际化(实现MessageSource接口)。
(2)访问资源(实现ResourcePatternResolver接口,后面章节会讲到)。
(3)支持应用事件(实现ApplicationEventPublisher接口)。


18、什么是控制反转(IoC),什么是依赖注入
(1)控制反转是应用于软件工程领域的,在运行时被装配器对象用来绑定耦合对象的一种编程技巧,对象之间的耦合关系在编译时通常是未知的。在传统的编程方式中,业务逻辑的流程是由应用程序中早已被设定好关联关系的对象来决定的。在使用控制反转的情况下,业务逻辑的流程是由对象关系图来决定的,该对象关系图由装配器负责实例化,这种实现方式还可以将对象之间的关联关系的定义抽象化。绑定的过程是通过“依赖注入”实现的。
(2)控制反转是一种以给予应用程序中目标组件更多控制为目的设计范式,并在实际工作中起到了有效的作用。
(3)依赖注入是在编译阶段尚未知所需的功能是来自哪个的类的情况下,将其他对象所依赖的功能对象实例化的模式。这就需要一种机制来激活相应的组件以提供特定的功能,所以依赖注入是控制反转的基础。否则如果在组件不受框架控制的情况下,框架又怎么知道要创建哪个组件呢?

19、下面是几种比较重要的注解类型。
(1)@Required:该注解应用于设值方法。
(2)@Autowired:该注解应用于设值方法、非设值方法、构造方法和变量。
(3)@Qualifier:该注解和@Autowired注解搭配使用,用于消除特定Bean自动装配的歧义。
(4)JSR-250 Annotations:Spring支持基于JSR-250 注解的注解,即@Resource、@PostConstruct和@PreDestroy。

20、Spring容器中的Bean可以分为5个作用域
1)singleton:这种Bean作用域是默认的,这种作用域确保不管接收到多少个请求,每个容器中只有一个Bean实例,单例模式由Bean Factory自身来维护。
(2)prototype:prototype作用域与singleton作用域相反,为每一个Bean请求提供一个实例。
(3)request:在请求 Bean 作用域内为每一个来自客户端的网络请求创建一个实例,在请求完成以后,Bean会失效并被垃圾回收器回收。
(4)Session:与request作用域类似,确保每个Session中有一个Bean实例,在Session过期后,Bean会随之失效。
(5)global-session:global-session和Portlet应用相关。当应用部署在Portlet容器中时,它包含很多 Portlet。如果想让所有的 Portlet 共用全局存储变量,那么这个全局存储变量需要存储在global-session中。全局作用域与Servlet中的Session作用域效果相同。
在 Spring中,无论何时,当 Bean仅被调用了一个属性时,一个明智的做法是将这个 Bean声明为内部Bean。内部Bean可以用setter注入“属性”和用构造方法注入“构造参数”的方式来实现。
Spring提供了以下4种集合类的配置元素:
(1)<list>标签用来装配可重复的list值。
(2)<set>标签用来装配没有重复的set值。
(3)<map>标签用来注入键和值,可以为任何类型的键值对。
(4)<props>标签支持注入键和值都是字符串类型的键值对。


21.自动装配有哪些局限性
自动装配有如下局限性。
· 重写:你仍然需要使用<property>设置指明依赖,这意味着总要重写自动装配。
· 原生数据类型:你不能自动装配简单的属性,如原生类型、字符串和类。
· 模糊特性:自动装配总是没有自定义装配精确,因此如果可能尽量使用自定义装配。


22、自动装配类型:
(1)no:这是Spring的默认设置,在该设置下自动装配是关闭的,开发者需要自行在Bean定义中用标签明确地设置依赖关系。
(2)byName:该模式可以根据Bean名称设置依赖关系。当向一个Bean中自动装配一个属性时,容器将根据 Bean 的名称自动在配置文件中查询一个匹配的 Bean。如果找到就装配这个属性,如果没找到就报错。
(3)byType:该模式可以根据Bean类型设置依赖关系。当向一个Bean中自动装配一个属性时,容器将根据Bean的类型自动在配置文件中查询一个匹配的Bean。如果找到就装配这个属性,如果没找到就报错。
(4)constructor:和 byType 模式类似,但是仅适用于有与构造器相同参数类型的 Bean,如果在容器中没有找到与构造器参数类型一致的Bean,那么将会抛出异常。
(5)autodetect:该模式自动探测使用constructor自动装配或者byType自动装配。首先会尝试找合适的带参数的构造器,如果找到就是用构造器自动装配,如果在Bean内部没有找到相应的构造器或者构造器是无参构造器,容器就会自动选择byType模式。

你可能感兴趣的:(spring,设计模式,java)