每日一看 巩固知识


前言

每天都看一遍复习所学


1、sql索引的知识?

如果语句只访问索引的列,则 Oracle 数据库直接从索引中读取索引列值,而不是从表中读取

1.1索引的优缺点

优点:大大加快数据的查询速度
缺点:1.创建索引和维护索引需要消耗大量时间,并且随着数据量的增加所耗费的时间也会增加
2.索引也需要占空间,我们知道数据表中的数据也会有最大上线设置的,如果我们有大量的索引,索引文件可能会比数据文件更快达到上线值
3.当对表中的数据进行增加、删除、修改时,索引也需要动态的维护,降低了数据的维护速度
总结:需要合理的使用索引
1、对经常更新的表就避免对其进行过多的索引,对经常用于查询的字段应该创建索引
2、数据量小的表最好不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果
3、在一同值少的列上(字段上)不要建立索引,比如在学生表的"性别"字段上只有男,女两个不同值。相反的,在一个字段上不同值较多可是建立索引

1.2索引的分类

注意:索引是在存储引擎中实现的,也就是说不同的存储引擎,会使用不同的索引
如果需要索引的列使用函数那就创建函数索引(降序索引为函数索引)

1.3全扫描

1.ORDER BY查询中存在满足以下要求的子句
1.1子句中的所有列都ORDER BY必须在索引中
1.2子句中列的ORDER BY顺序必须与前导索引列的顺序相匹配
该ORDER BY子句可以包含索引中的所有列或索引中列的子集
2.查询中引用的所有列都必须在索引中
查询中引用的列的顺序必须与前导索引列的顺序相匹配
查询可以包含索引中的所有列或索引中列的子集
3.GROUP BY查询中存在子句,并且子句中的列存在GROUP BY于索引中。GROUP BY列在索引和子句中的顺序不需要相同。该GROUP BY子句可以包含索引中的所有列或索引中列的子集
如果查询选择的所有列都在复合索引中,则 Oracle 数据库可以从索引中返回这些值,而无需访问表

1.4索引的失效

1、当查询中的索引列使用了函数或运算符
2、索引键中的至少一个列具有NOT NULL约束时
3、模糊查询 like 后面%不会失效 前面% 会使索引失效
4、使用!= 或<>
5、联合索引没有遵循左前缀及前导索引列原则 (查询使用索引的列的顺序与创建索引的顺序要匹配也不可以缺少前面索引)

InnoDB只有在通过索引条件检索数据时使用行级锁,否则使用表锁
InnoDB的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为表锁
索引失效全表扫描,行锁变表锁

2其他优化

1、 不要在where语句中使用sql函数
2 、避免混合模式表达方式,谨防隐含的类型转换 (AND charcol = numexpr (charcol 是varchar,numexpr 是数字)数据库将该表达式转换为AND TO_NUMBER(charcol) = numexpr)
3、避免以下类型的复杂表达式(col1 = NVL (:b1,col1)、NVL (col1,-999) = ….、TO_DATE()、TO_NUMBER() 等)
4、 使用触发器会消耗系统资源。如果您使用太多触发器,则性能可能会受到不利影响

3 spring

3.1 spring的了解

spring提供每个级别的选择、容纳不同的观点、保持强大的向后兼容性、关心 API 设计、为代码质量设定高标准

3.2 IOC

控制反转 (IoC) :IoC 也被称为依赖注入(DI) 对象仅通过 构造参数 、工厂方法参数、在对象实例被构造或从工厂方法返回后设置的属性 定义他们的的依赖关系 容器在创建bean的时候注入这些依赖项,这个过程基本上是 bean 本身通过使用类的直接构造或诸如服务定位器模式之类的机制来控制其依赖关系的实例化或位置的逆过程(因此称为控制反转)

3.3容器概述

ApplicationContext接口代表 Spring IoC 容器,负责实例化、配置和组装 bean,容器通过读取配置元数据来获取关于要实例化、配置和组装哪些对象的指令,配置元数据以 XML、Java 注释或 Java 代码表示,它允许您表达组成应用程序的对象以及这些对象之间丰富的相互依赖关系。

3.3.1配置元数据

Spring 配置包含容器必须管理的至少一个,通常是多个 bean 定义。基于 XML 的配置元数据将这些 bean 配置为顶级元素内的元素,Java 配置通常@Bean在类中使用 -annotated 方法@Configuration。
基于 XML 的配置元数据的基本结构

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." class="...">  
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>

1、该id属性是标识单个 bean 定义的字符串
2、该class属性定义 bean 的类型并使用完全限定的类名。

3.3.2 实例化一个容器

提供给构造函数的一个或多个位置路径ApplicationContext是资源字符串,允许容器从各种外部资源(例如本地文件系统、Java 等)加载配置元数据CLASSPATH

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

基于 XML 的配置元数据
bean定义跨越多个xml文件会很有用
xml可以使用元素的一个或多个实例从另一个文件或多个文件加载 bean 定义

<beans>
	<!-- 同级路径-- >
    <import resource="services.xml"/>
    <!--resources路径下 -- >
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>
    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

注:可以但不推荐使用相对“…/”路径来引用父目录中的文件。这样做会创建对当前应用程序之外的文件的依赖

3.3.3 使用容器

applicationContext是一个高级工厂接口,能够维护不同bean 及其依赖项的注册表,通过使用 method T getBean(String name, Class requiredType),您可以检索 bean 的实例
理想情况下我们不应该使用getbean来检索bean实例。ApplicationContext 接口还有一些其他检索 bean 的方法,但理想情况下,您的应用程序代码不应该使用它们。实际上,您的应用程序代码根本不应该调用该 getBean()方法,因此根本不依赖 Spring API

3.3.4命名bean

每个 bean 都有一个或多个标识符。这些标识符在承载 bean 的容器中必须是唯一的。一个 bean 通常只有一个标识符。但是,如果它需要多个,则可以将多余的视为别名。
在基于 XML 的配置元数据中,您可以使用id属性、name属性或两者来指定 bean 标识符。
如果要为 bean 引入其他别名,也可以在name 属性中指定,用逗号 ( ,)、分号 ( ; ) 或空格分隔。
您不需要为 bean 提供 ame或 id。如果您不显式提供 name或id,则容器会为该 bean 生成一个唯一名称。但是,如果您想通过名称引用该 bean,通过使用ref元素或服务定位器样式查找,您必须提供名称。不提供名称的动机与使用内部 bean和自动装配合作者有关
bean的命名约定
约定是在命名 bean 时对实例字段名称使用标准 Java 约定。也就是说,bean 名称以小写字母开头,并且从那里开始是驼峰式的。此类名称的示例包括accountManager、 accountService、userDao、loginController等。
一致地命名 bean 使您的配置更易于阅读和理解。此外,如果您使用 Spring AOP,则在将建议应用于一组按名称相关的 bean 时会很有帮助
在 Bean 定义之外为 Bean 起别名
在 bean 定义本身中,您可以为 bean 提供多个名称,方法是使用属性指定的最多一个名称id和属性中任意数量的其他名称的组合name。这些名称可以是同一个 bean 的等效别名,并且在某些情况下很有用,例如让应用程序中的每个组件通过使用特定于该组件本身的 bean 名称来引用公共依赖项

3.3.5实例化bean

通常,在容器本身通过反射调用其构造函数直接创建 bean 的情况下,指定要构造的 bean 类,有点等价于 Java 代码中的new运算符
static指定包含被调用以创建对象 的工厂方法的实际类,在不太常见的情况下,容器调用static类上的工厂方法来创建 bean。调用static工厂方法返回的对象类型可能是同一个类,也可能完全是另一个类
使用构造函数进行实例化
当您通过构造方法创建 bean 时,所有普通类都可以被 Spring 使用并兼容。也就是说,正在开发的类不需要实现任何特定的接口或以特定的方式进行编码。只需指定 bean 类就足够了。但是,根据您用于该特定 bean 的 IoC 类型,您可能需要一个默认(空)构造函数。
Spring IoC 容器几乎可以管理您希望它管理的任何类。它不仅限于管理真正的 JavaBean。大多数 Spring 用户更喜欢只有一个默认(无参数)构造函数以及根据容器中的属性建模的适当的 setter 和 getter 的实际 JavaBeans
使用静态工厂方法进行实例化
在定义使用静态工厂方法创建的 bean 时,使用class 属性指定包含static工厂方法的类,使用命名属性factory-method指定工厂方法本身的名称。您应该能够调用此方法(使用可选参数,如后所述)并返回一个活动对象,该对象随后被视为是通过构造函数创建的。这种 bean 定义的一种用途是static在遗留代码中调用工厂
使用实例工厂方法进行实例化
与通过静态工厂方法进行实例化类似,使用实例工厂方法进行实例化会从容器中调用现有 bean 的非静态方法来创建新 bean。要使用此机制,请将class属性留空,并在factory-bean属性中指定当前(或父级或祖先)容器中包含要调用以创建对象的实例方法的 bean 的名称。factory-method使用属性设置工厂方法本身的名称

<bean id="serviceLocator" class="examples.DefaultServiceLocator">
    <!-- inject any dependencies required by this locator bean -->
</bean>

<bean id="clientService"
    factory-bean="serviceLocator"
    factory-method="createClientServiceInstance"/>

<bean id="accountService"
    factory-bean="serviceLocator"
    factory-method="createAccountServiceInstance"/>
public class DefaultServiceLocator {

    private static ClientService clientService = new ClientServiceImpl();

    private static AccountService accountService = new AccountServiceImpl();

    public ClientService createClientServiceInstance() {
        return clientService;
    }

    public AccountService createAccountServiceInstance() {
        return accountService;
    }
}

确定 Bean 的运行时类型
bean 元数据定义中的指定类只是一个初始类引用,可能与声明的工厂方法结合,或者是FactoryBean可能导致 bean 的不同运行时类型的类,或者在实例的情况下根本没有设置 -级别工厂方法(而是通过指定的factory-bean名称解析)。此外,AOP 代理可以用基于接口的代理包装一个 bean 实例,并限制目标 bean 的实际类型(仅其实现的接口)的暴露

3.4 依赖项

3.4.1依赖注入

依赖注入 (DI) 是一个过程,对象仅通过构造函数参数、工厂方法的参数或对象实例在构造或从工厂方法返回。然后容器在创建 bean 时注入这些依赖项。这个过程基本上是 bean 本身通过使用直接构造类或服务定位器模式来控制其依赖项的实例化或位置的逆过程(因此称为控制反转)
使用 DI 原则,代码更干净,当对象具有依赖关系时,解耦更有效。对象不查找其依赖项,也不知道依赖项的位置或类别
基于构造函数的依赖注入
基于构造函数的 DI 是通过容器调用具有多个参数的构造函数来完成的,每个参数代表一个依赖项。调用static带有特定参数的工厂方法来构造 bean 几乎是等价的,本次讨论将类似地对待构造函数和static工厂方法的参数
构造函数参数解析
构造函数参数解析匹配通过使用参数的类型进行。如果 bean 定义的构造函数参数中不存在潜在的歧义,则在 bean 定义中定义构造函数参数的顺序是在实例化 bean 时将这些参数提供给适当构造函数的顺序
:构造函数参数类型匹配(则容器可以使用简单类型的类型匹配type)

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>

:构造函数参数索引(可以使用该index属性显式指定构造函数参数的索引)

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>

:构造函数参数名称(可以使用构造函数参数名称进行值消歧)
可以使用 @ConstructorProperties JDK 注释显式命名构造函数参数

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>
package examples;

public class ExampleBean {

    // Fields omitted

    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}

基于 Setter 的依赖注入
基于 Setter 的 DI 是通过容器在调用无参数构造函数或无参数static工厂方法来实例化 bean 后调用 bean 上的 setter 方法来完成的
在 setter 方法上使用@Required 注释可用于使属性成为必需的依赖项
依赖解决过程
Spring 容器在创建容器时验证每个 bean 的配置。但是,在实际创建 bean 之前,不会设置 bean 属性本身。在创建容器时会创建单例范围并设置为预实例化(默认)的 Bean。范围在Bean Scopes中定义。否则,只有在请求时才会创建 bean。创建 bean 可能会导致创建 bean 图,因为创建和分配 bean 的依赖项及其依赖项的依赖项(等等)。请注意,这些依赖项之间的解析不匹配可能会出现较晚 - 即在第一次创建受影响的 bean 时
循环依赖
如果您主要使用构造函数注入,则可能会创建无法解决的循环依赖场景
例如:A类通过构造函数注入需要B类的实例,B类通过构造函数注入需要A类的实例。如果你为类 A 和 B 配置 bean 以相互注入,Spring IoC 容器会在运行时检测到这个循环引用,并抛出一个 BeanCurrentlyInCreationException
一种可能的解决方案是编辑某些类的源代码以由设置器而不是构造器配置。或者,避免构造函数注入并仅使用 setter 注入。也就是说,虽然不推荐,但是可以通过setter注入来配置循环依赖
idref元素
元素只是将容器中另一个 bean 的(字符串值 - 不是引用)传递给or元素的一种idref防错方法

<bean id="theTargetBean" class="..."/>

<bean id="theClientBean" class="...">
    <property name="targetName">
        <idref bean="theTargetBean"/>
    </property>
</bean>

和这个相同(运行时)

<bean id="theTargetBean" class="..." />

<bean id="client" class="...">
    <property name="targetName" value="theTargetBean"/>
</bean>

第一种形式比第二种形式更可取,因为使用idref标签可以让容器在部署时验证所引用的命名 bean 确实存在。在第二个变体中,不对传递给beantargetName属性的值执行验证。只有在实际实例化 beanclient时才会发现拼写错误(很可能是致命的结果) 。client如果client bean 是一个原型bean,那么这个拼写错误和产生的异常可能只有在容器部署很久之后才会被发现
<idref/>元素带来价值的常见地方(至少在 Spring 2.0 之前的版本中)是在 bean 定义中的AOP 拦截器配置中。ProxyFactoryBean在指定拦截器名称时使用元素可以防止您拼错拦截器 ID
内部 bean

<bean id="outer" class="...">
    <!-- instead of using a reference to a target bean, simply define the target bean inline -->
    <property name="target">
        <bean class="com.example.Person"> <!-- this is the inner bean -->
            <property name="name" value="Fiona Apple"/>
            <property name="age" value="25"/>
        </bean>
    </property>
</bean

内部 bean 定义不需要定义的 ID 或名称。如果指定,容器不会使用这样的值作为标识符。容器在创建时也会忽略该scope标志,因为内部 bean 始终是匿名的,并且始终使用外部 bean 创建。不可能独立访问内部 bean 或将它们注入到协作 bean 中,而不是注入封闭 bean。
作为一个极端情况,可以从自定义范围接收销毁回调 - 例如,对于包含在单例 bean 中的请求范围内的内部 bean。内部 bean 实例的创建与其包含的 bean 相关联,但销毁回调让它参与请求范围的生命周期。这不是常见的情况。内部 bean 通常只是共享其包含 bean 的范围。

<bean id="moreComplexObject" class="example.ComplexObject">
    <!-- results in a setAdminEmails(java.util.Properties) call -->
    <property name="adminEmails">
        <props>
            <prop key="administrator">administrator@example.org</prop>
            <prop key="support">support@example.org</prop>
            <prop key="development">development@example.org</prop>
        </props>
    </property>
    <!-- results in a setSomeList(java.util.List) call -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- results in a setSomeMap(java.util.Map) call -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- results in a setSomeSet(java.util.Set) call -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>

depends-on
如果一个 bean 是另一个 bean 的依赖项,那通常意味着一个 bean 被设置为另一个 bean 的属性。通常,您使用基于 XML 的配置元数据中的 元素来完成此操作。但是,有时 bean 之间的依赖关系不那么直接。例如,当需要触发类中的静态初始化程序时,例如用于数据库驱动程序注册。在初始化使用此元素的 bean 之前,该depends-on属性可以显式强制初始化一个或多个 bean;

<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
<bean id="manager" class="ManagerBean" />

要表达对多个 bean 的依赖关系,请提供 bean 名称列表作为depends-on属性值(逗号、空格和分号是有效的分隔符)

<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
    <property name="manager" ref="manager" />
</bean>

<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />

3.4.2 延迟初始化的 Bean

默认情况下,作为初始化过程的一部分,ApplicationContext实现会急切地创建和配置所有 单例bean。通常,这种预实例化是可取的,因为配置或周围环境中的错误会立即发现,而不是几小时甚至几天之后。当这种行为不可取时,您可以通过将 bean 定义标记为延迟初始化来防止单例 bean 的预实例化。延迟初始化的 bean 告诉 IoC 容器在第一次被请求时创建一个 bean 实例,而不是在启动时。
在 XML 中,此行为由元素lazy-init上的属性控制<bean/>

<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>
<bean name="not.lazy" class="com.something.AnotherBean"/>

3.4.3自动装配协作者

Spring 容器可以自动装配协作 bean 之间的关系。您可以通过检查ApplicationContext. 自动装配具有以下优点:
1、自动装配可以显着减少指定属性或构造函数参数的需要
2、随着对象的发展,自动装配可以更新配置。例如,如果您需要向类添加依赖项,则可以自动满足该依赖项,而无需修改配置。因此,自动装配在开发过程中特别有用,而不会在代码库变得更稳定时否定切换到显式装配的选项
no
(默认)不自动装配。Bean 引用必须由ref元素定义。对于较大的部署,不建议更改默认设置,因为明确指定协作者可以提供更大的控制力和清晰度。在某种程度上,它记录了系统的结构。
byName
按属性名称自动装配。Spring 寻找与需要自动装配的属性同名的 bean。例如,如果一个 bean 定义被设置为按名称自动装配并且它包含一个master属性(即它有一个 setMaster(…)方法),那么 Spring 会查找一个命名的 bean 定义master并使用它来设置该属性。
byType
如果容器中恰好存在一个属性类型的 bean,则让属性自动装配。如果存在多个,则会抛出一个致命异常,这表明您可能不会byType对该 bean 使用自动装配。如果没有匹配的 bean,则不会发生任何事情(未设置属性)。
constructor
类似于byType但适用于构造函数参数。如果容器中没有一个构造函数参数类型的 bean,则会引发致命错误。
使用byType或constructor自动装配模式,您可以连线数组和类型化集合。在这种情况下,将提供容器中与预期类型匹配的所有自动装配候选者来满足依赖关系。Map如果预期的键类型是 ,您可以自动装配强类型实例String。自动装配Map 实例的值包含与预期类型匹配的所有 bean 实例,并且 Map实例的键包含相应的 bean 名称
自动装配的限制和缺点
自动装配的限制和缺点:
1、property和设置中的显式依赖constructor-arg项总是覆盖自动装配。您不能自动装配简单属性,例如基元、、 Strings和Classes(以及此类简单属性的数组)。此限制是设计使然。
2、自动装配不如显式装配精确。尽管如前表中所述,Spring 会小心避免猜测可能会产生意想不到的结果的歧义。Spring 管理的对象之间的关系不再明确记录
3、从 Spring 容器生成文档的工具可能无法使用接线信息。
4、容器内的多个 bean 定义可能与要自动装配的 setter 方法或构造函数参数指定的类型匹配。对于数组、集合或 Map实例,这不一定是问题。但是,对于期望单个值的依赖项,这种歧义不会被任意解决。如果没有唯一的 bean 定义可用,则会引发异常
在后一种情况下,您有多种选择:
1、放弃自动装配以支持显式装配。
2、autowire-candidate通过将其属性设置为 来避免对 bean 定义进行自动装配false,如下一节所述。
3、通过将其元素的primary属性设置为 ,将单个 bean 定义指定为主要候选者 。<bean/>true
4、使用基于注释的配置实现更细粒度的控制,如基于注释的容器配置中所述
从自动装配中排除 Bean
在每个 bean 的基础上,您可以从自动装配中排除 bean。将元素的autowire-candidate属性设置为false
注:该autowire-candidate属性旨在仅影响基于类型的自动装配。它不会影响按名称的显式引用,即使指定的 bean 未标记为自动装配候选者,也会得到解析。因此,如果名称匹配,按名称自动装配仍然会注入一个 bean。
您还可以根据与 bean 名称的模式匹配来限制自动装配候选者。顶级元素在其 default-autowire-candidates属性中接受一个或多个模式。例如,要将自动装配候选状态限制为名称以 结尾的任何 bean Repository,请提供*Repository. 要提供多种模式,请在逗号分隔的列表中定义它们。bean 定义属性的显式值 trueor始终优先。对于此类 bean,模式匹配规则不适用。falseautowire-candidate

3.5bean范围

3.5.1singleton(单例模式)

只有一个单例 bean 的共享实例被管理,并且所有对具有与该 bean 定义匹配的一个或多个 ID 的 bean 的请求都会导致 Spring 容器返回一个特定的 bean 实例。
换句话说,当您定义 bean 定义并将其限定为单例时,Spring IoC 容器会创建该 bean 定义所定义的对象的一个​​实例。此单个实例存储在此类单例 bean 的缓存中,并且该命名 bean 的所有后续请求和引用都返回缓存的对象。
当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换言之,当把一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都将返回被缓存的对象实例,这里要注意的是singleton作用域和GOF设计模式中的单例是完全不同的,单例设计模式表示一个ClassLoader中只有一个class存在,而这里的singleton则表示一个容器对应一个bean,也就是说当一个bean被标识为singleton时候,spring的IOC容器中只会存在一个该bean

3.5.2prototy(原型模式)

bean 部署的非单例原型范围导致每次对特定 bean 发出请求时都会创建一个新的 bean 实例。也就是说,将 bean 注入到另一个 bean 中,或者您通过getBean()容器上的方法调用来请求它。
Spring 不管理原型 bean 的完整生命周期。
容器实例化、配置和以其他方式组装原型对象并将其传递给客户端,而没有该原型实例的进一步记录。
原型的情况下,不会调用配置的销毁生命周期回调。
客户端代码必须清理原型范围的对象并释放原型 bean 拥有的昂贵资源。要让 Spring 容器释放原型范围 bean 持有的资源,请尝试使用自定义bean 后处理器,它包含对需要清理的 bean 的引用

3.5.3 生命周期回调

当您编写不使用 Spring 特定InitializingBean和DisposableBean回调接口的初始化和销毁​​方法回调时,您通常会编写名称为init()、initialize()、dispose()等的方法。理想情况下,此类生命周期回调方法的名称在整个项目中是标准化的,以便所有开发人员使用相同的方法名称并确保一致性。
您可以将 Spring 容器配置为“查找”命名初始化并销毁每个 bean 上的回调方法名称。这意味着,作为应用程序开发人员,您可以编写应用程序类并使用名为 的初始化回调 init(),而无需为init-method="init"每个 bean 定义配置属性。Spring IoC 容器在创建 bean 时调用该方法(并根据前面描述的标准生命周期回调协定)。此功能还为初始化和销毁​​方法回调强制执行一致的命名约定
结合生命周期机制
您可以通过三个选项来控制 bean 生命周期行为
1、和InitializingBean回调 DisposableBean接口
2、自定义init()和destroy()方法
3、@PostConstruct和@PreDestroy 注解。_ 您可以结合这些机制来控制给定的 bean
注: 如果为一个 bean 配置了多个生命周期机制,并且每个机制都配置了不同的方法名称,那么每个配置的方法都按照本注释后列出的顺序运行。如果为多个生命周期机制 配置了相同的方法名称(例如, 对于初始化方法),则该方法将运行一次
为同一个bean配置的多个生命周期机制,不同的初始化方法调用顺序:
1、用注释的方法@PostConstruct
2、afterPropertiesSet()由InitializingBean回调接口定义
3、自定义配置init()方法
销毁方法的调用顺序:
1、用注释的方法@PreDestroy
2、destroy()由DisposableBean回调接口定义
3、自定义配置destroy()方法
启动和关闭回调
Lifecycle接口定义了任何具有自己生命周期要求的对象的基本方法(例如启动和停止某些后台进程)

public interface Lifecycle {

    void start();

    void stop();

    boolean isRunning();
}

任何 Spring 管理的对象都可以实现该Lifecycle接口。然后,当 ApplicationContext自身接收到启动和停止信号时(例如,对于运行时的停止/重新启动场景),它会将这些调用级联到Lifecycle该上下文中定义的所有实现。它通过委托LifecycleProcessor做到这一点

public interface LifecycleProcessor extends Lifecycle {

    void onRefresh();

    void onClose();
}

LifecycleProcessor它本身就是Lifecycle 接口的扩展。它还添加了另外两种方法来对正在刷新和关闭的上下文做出反应
:常规org.springframework.context.Lifecycle接口是显式启动和停止通知的简单约定,并不意味着在上下文刷新时自动启动。要对特定 bean 的自动启动(包括启动阶段)进行细粒度控制,请考虑实施org.springframework.context.SmartLifecycle。停止通知不能保证在销毁之前发出。在常规关闭时,所有Lifecyclebean 在传播一般销毁回调之前首先收到停止通知。但是,在上下文的生命周期内进行热刷新或停止刷新尝试时,只会调用销毁方法

3.6容器扩展点

3.7基于注解的容器配置

3.7.1@Required

注释适用于 bean 属性设置方法:注解指示必须在配置时通过 bean 定义中的显式属性值或通过自动装配来填充受影响的 bean 属性。如果受影响的 bean 属性尚未填充,则容器将引发异常。这允许急切和明确NullPointerException 的失败,避免以后出现实例等

3.7.2@Autowired

可以将@Autowired注释应用于构造函数
可以将@Autowired注解应用于传统的setter 方法
可以将注释应用于具有任意名称和多个参数的方法
可以应用于@Autowired字段,甚至可以将其与构造函数混合使用
可以通过将@Autowired注释添加到需要该类型数组的字段或方法来指示 Spring 提供特定类型的所有 bean

用于带@Autowired注释的注入点的类型声明预先知道具体类型

3.7.3微调基于注释的自动装配@Primary

按类型自动装配可能会导致多个候选者,因此通常需要对选择过程进行更多控制。实现这一点的一种方法是使用 Spring 的 @Primary注释。@Primary指示当多个 bean 是自动装配到单值依赖项的候选对象时,应该优先考虑特定的 bean。如果候选中恰好存在一个主 bean,则它将成为自动装配的值

@Configuration
public class MovieConfiguration {

    @Bean
    @Primary
    public MovieCatalog firstMovieCatalog() { ... }

    @Bean
    public MovieCatalog secondMovieCatalog() { ... }

    // ...
}

public class MovieRecommender {

    @Autowired
    private MovieCatalog movieCatalog;

    // ...
}

使用限定符微调基于注释的自动装配
@Primary当可以确定一个主要候选者时,是一种通过类型使用多个实例的自动装配的有效方法。当您需要对选择过程进行更多控制时,可以使用 Spring 的@Qualifier注解。您可以将限定符值与特定参数相关联,缩小类型匹配的范围,以便为每个参数选择特定的 bean

public class MovieRecommender {

    @Autowired
    @Qualifier("main")
    private MovieCatalog movieCatalog;

    // ...
}

@Qualifier在单​​个构造函数参数或方法参数上指定注释

public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(@Qualifier("main") MovieCatalog movieCatalog,
            CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...
}

**注:**在类型匹配的候选对象中,让限定符值针对目标 bean 名称进行选择,不需要@Qualifier在注入点进行注释。如果没有其他解析指示符(例如限定符或主标记),对于非唯一依赖情况,Spring 将注入点名称(即字段名称或参数名称)与目标 bean 名称匹配并选择同名候选人(如有)

使用@Resource,它可以通过其唯一名称获取返回到当前 bean 的代理
@Autowired按类型选择候选 bean

@Autowired适用于字段、构造函数和多参数方法,允许在参数级别通过限定符注释缩小范围。相反,@Resource 仅支持具有单个参数的字段和 bean 属性设置器方法。因此,如果您的注入目标是构造函数或多参数方法,您应该坚持使用限定符

3.7.4@Resource

Spring 还通过在字段或 bean 属性设置器方法上使用 JSR-250@Resource注释 ( )来支持注入
@Resource采用名称属性。默认情况下,Spring 将该值解释为要注入的 bean 名称。换句话说,它遵循按名称语义
如果没有明确指定名称,则默认名称派生自字段名称或 setter 方法。如果是字段,则采用字段名称。对于 setter 方法,它采用 bean 属性名称

3.7.5@Value

@Value通常用于注入外部属性
Spring 提供的内置转换器支持允许自动处理简单的类型转换(toInteger 或example)。int多个逗号分隔的值可以自动转换为String数组,无需额外的努力

3.7.6@PostConstruct和@PreDestroy

3.8类路径扫描和托管组件

3.8.1@Component和进一步的刻板印象注释

@Repository注释是满足存储库(也称为数据访问对象或 DAO)角色或原型的任何类的标记
Spring 提供了更多的原型注解:@Component、@Service和 @Controller.
@Component是任何 Spring 管理的组件的通用构造型。
@Repository, @Service, 和@Controller是@Component针对更具体用例(分别在持久层、服务层和表示层)的特化。
因此,您可以使用 注释组件类 @Component,但是通过使用 @Repository,@Service或者@Controller 注释它们,您的类更适合工具处理或与方面关联

3.8.2使用元注释和组合注释

Spring 提供的许多注解都可以在您自己的代码中用作元注解。元注释是可以应用于另一个注释的注释。例如,前面提到的注释@Service是 用 元注释的
您还可以组合元注释来创建“组合注释”。例如,@RestControllerSpring MVC 的注解由@Controller和 组成@ResponseBody

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值