Spring IOC

一、Spring框架

Spring是轻量级开源框架,以IOC反转控制和AOP面向切面编程为内核,提供了展现层的MVC和持久层JDBC以及业务层事务管理等技术,还能整合很多第三方框架和类库。

看下Spring 框架图,在Spring中有核心容器,Core Container即是IOC部分,这里面就有Bean。
在这里插入图片描述

二、程序的耦合和解耦

在一般情况下我们写CSD三层代码的时候使用直接new的方式来创建一个对象,这样程序之间的耦合性太大,如果编译的时候有一个层的实现类不存在的的时候,则编译器将不会通过,这样以来,它就是一个编译器依赖。

  • 耦合: 程序间的依赖关系.在开发中,应该做到解决编译期依赖,即编译期不依赖,运行时才依赖.
  • 解耦的思路: 使用反射来创建对象,而避免使用new关键字,并通过读取配置文件来获取要创建的对象全限定类名

2.1 工厂模式解耦(这样解耦的目的是什么呢?)

在实际开发中可以把三层的对象的全类名都使用配置文件保存起来,当启动服务器应用加载的时候,创建这些对象的实例并保存在容器中. 在获取对象时,不使用new的方式,而是直接从容器中获取,这就是工厂设计模式.

2.1.1解耦的思路

1、使用反射来创建对象,避免使用new创建对象。

2、通过读取配置文件来获取要创建的对象权限定类名。

eg:

1、需要创建配置文件配置我们的Service和Dao

配置的内容:唯一标示=权限定类名(key=value)

2、通过读取配置文件配置的内容,反射创建对象(BeanFactory)

这个时候创建的多利对象。

这个时候可以用map进行存储Bean,根据name去获取Bean,保证单例对象。

三、IOC是什么

IOC的概念为:
当使用new创建对象的时候,等于找对象是主动找的,资源是直接相连接,这个时候它们的联系是消除不掉的。

而使用工厂模式的时候,工厂控制资源,工厂提供给获取方资源,获取方和资源断开连接。

上面这种思想就叫IOC控制反转(为什么不叫降低依赖?因为它把找到相应的对象的权利丢弃,交给BeanFactory来通过名字获取Bean对象,工厂所能得到哪个Bean对象是根据配置所对应的权限和类名所决定的,使用它的类无法自助决定的。所以叫做控制反转)

所以IOC的作用就是消减计算机程序之间的耦合,解除代码之间的依赖关系。(注意只能是削减,不是完全解除耦合关系)

Ioc—Inversion of Control,不是什么技术,而是一种设计思想。

  • 谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

  • 为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

四、bean

4.1 Bean的概念

  • Bean:可重用组件的含义。
  • JavaBean:用Java写的可重用组件。
    Spring 来管理Bean,那么肯定会把Bean存放在容器中,那么Spring是如何获取到Bean的呢?

4.2 bean的作用范围和生命周期

  1. 单例对象: scope=“singleton”
    • 作用范围: 每个应用只有一个该对象的实例,它的作用范围就是整个应用
    • 生命周期: 单例对象的创建与销毁 和 容器的创建与销毁时机一致
      • 对象出生: 当应用加载,创建容器时,对象就被创建
      • 对象活着: 只要容器存在,对象一直活着
      • 对象死亡: 当应用卸载,销毁容器时,对象就被销毁
  2. 多例对象: scope=“prototype”
    • 作用范围: 每次访问对象时,都会重新创建对象实例.
    • 生命周期: 多例对象的创建与销毁时机不受容器控制
      • 对象出生: 当使用对象时,创建新的对象实例
      • 对象活着: 只要对象在使用中,就一直活着
      • 对象死亡: 当对象长时间不用时,被 java 的垃圾回收器回收了

4.3 IOC依赖注入后的bean放在哪

建立存放Bean中id和Class的类——BeanDefinition。
这里存放的是Bean的内容和元数据,保存在BeanFactory当中,包装Bean的实体:

public class BeanDefinition {
    //真正的Bean实例
    private Object bean;
    //Bean的类型信息
    private Class beanClass;
    //Bean类型信息的名字
    private String beanClassName;
    //用于bean的属性注入 因为Bean可能有很多熟属性
    //所以这里用列表来进行管理
    private PropertyValues propertyValues = new PropertyValues();
}

其中的PerpertyValues存放Bean的所有属性

public class PropertyValues {
    private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>();
}

其中ArrayList数组中的PropertyValue存放的是每个属性,可以看到两个字段,name和valu。name存放的就是属性名称,value是object类型,可以是任何类型

public class PropertyValue {
    private final String name;
    private final Object value;
}

把Bean装进容器的过程,其实就是其BeanDefinition构造的过程,那么怎么把一些类装入的Spring容器呢?
//TODO:后面分析下如何处理的。

五、依赖注入DI

5.1 依赖注入的概念

依赖注入(Dependency Injection)是spring框架核心ioc的具体实现.
通过控制反转,我们把创建对象托管给了spring,但是代码中不可能消除所有依赖,例如:业务层仍然会调用持久层的方法,因此业务层类中应包含持久化层的实现类对象.
我们等待框架通过配置的方式将持久层对象传入业务层,而不是直接在代码中new某个具体的持久化层实现类,这种方式称为依赖注入.
“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么

  1. 谁依赖于谁:是应用程序依赖于IoC容器;
  2. 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
  3. 谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
  4. 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

5.2 依赖注入的方法

因为我们是通过反射的方式来创建属性对象的,而不是使用new关键字,因此我们要指定创建出对象各字段的取值.

5.2.1 使用构造函数注入

通过类默认的构造函数来给创建类的字段赋值,相当于调用类的构造方法.
涉及的标签: 用来定义构造函数的参数,其属性可大致分为两类:

  1. 寻找要赋值给的字段
    • index: 指定参数在构造函数参数列表的索引位置
    • type: 指定参数在构造函数中的数据类型
    • name:指定参数在构造函数中的变量名,最常用的属性
  2. 指定赋给字段的值
    • value: 给基本数据类型和String类型赋值
    • ref: 给其它Bean类型的字段赋值,ref属性的值应为配置文件中配置的Bean的id
public class AccountServiceImpl implements IAccountService {
//如果是经常变化的数据,并不适用于注入的方式
    private String name;
    private Integer age;
    private Date birthday;
     
    public AccountServiceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }
    public void saveAccount() {
        System.out.println(name+","+age+","+birthday);
    }
}

配置

<!-- 使用Date类的无参构造函数创建Date对象 -->
<bean id="now" class="java.util.Date" scope="prototype"></bean>

<bean id="accountService" class="cn.maoritian.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="myname"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<!-- birthday字段为已经注册的bean对象,其id为now -->
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>

5.2.2 使用set方法注入(更常用)

在类中提供需要注入成员属性的set方法,创建对象只调用要赋值属性的set方法.
涉及的标签: ,用来定义要调用set方法的成员. 其主要属性可大致分为两类:

  1. 指定要调用set方法赋值的成员字段
    • name:要调用set方法赋值的成员字段
  2. 指定赋给字段的值
    • value: 给基本数据类型和String类型赋值
    • ref: 给其它Bean类型的字段赋值,ref属性的值应为配置文件中配置的Bean的id
 public class AccountServiceImpl implements IAccountService {
        private String name;
        private Integer age;
        private Date birthday;
     
        public void setName(String name) {
            this.name = name;
        }
     
        public void setAge(Integer age) {
            this.age = age;
        }
     
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
     
     
        @Override
        public void saveAccount() {
            System.out.println(name+","+age+","+birthday);
        }
    }
<!-- 使用Date类的无参构造函数创建Date对象 -->
<bean id="now" class="java.util.Date" scope="prototype"></bean>
<bean id="accountService" class="cn.maoritian.service.impl.AccountServiceImpl">
<property name="name" value="myname"></property>
<property name="age" value="21"></property>
<!-- birthday字段为已经注册的bean对象,其id为now -->
<property name="birthday" ref="now"></property>
</bean>

5.2.3 注入集合字段

集合字段及其对应的标签按照集合的结构分为两类: 相同结构的集合标签之间可以互相替换.

只有键的结构:
- 数组字段: 标签表示集合,标签表示集合内的成员.
- List字段: 标签表示集合,标签表示集合内的成员.
- Set字段: 标签表示集合,标签表示集合内的成员.
其中,,标签之间可以互相替换使用.

键值对的结构:
- Map字段: 标签表示集合,标签表示集合内的键值对,其key属性表示键,value属性表示值.
- Properties字段: 标签表示集合,标签表示键值对,其key属性表示键,标签内的内容表示值.
其中,标签之间,,标签之间可以互相替换使用.

六、使用springIOC解决程序耦合

我们常用的容器有三种: ClassPathXmlApplicationContext,FileSystemXmlApplicationContext,AnnotationConfigApplicationContext.

  • ClassPathXmlApplicationContext: 它是从类的根路径下加载配置文件
  • FileSystemXmlApplicationContext: 它是从磁盘路径上加载配置文件
  • AnnotationConfigApplicationContext: 读取注解创建容器

七、使用XML配置文件实现IOC

使用配置文件实现IOC,要将托管给spring的类写进bean.xml配置文件中.

7.1 bean标签

作用: 配置托管给spring的对象,默认情况下调用类的无参构造函数,若果没有无参构造函数则不能创建成功
属性:

  • id: 指定对象在容器中的标识,将其作为参数传入getBean()方法可以获取获取对应对象.
  • class: 指定类的全类名,默认情况下调用无参构造函数
  • scope: 指定对象的作用范围,可选值如下
    • singleton: 单例对象,默认值
    • prototype: 多例对象
    • request: 将对象存入到web项目的request域中
    • session: 将对象存入到web项目的session域中
    • global session: 将对象存入到web项目集群的session域中,若不存在集群,则global session相当于session
  • init-method:指定类中的初始化方法名称,在对象创建成功之后执行
  • destroy-method:指定类中销毁方法名称,对prototype多例对象没有作用,因为多利对象的销毁时机不受容器控制

7.2 实例化 Bean 的三种方式

7.2.1 使用默认无参构造函数创建对象:

默认情况下会根据默认无参构造函数来创建类对象,若Bean类中没有默认无参构造函数,将会创建失败.

<bean id="accountService"
      class="cn.maoritian.service.impl.AccountServiceImpl"></bean>

7.2.2 使用静态工厂的方法创建对象:

创建静态工厂如下:

// 静态工厂,其静态方法用于创建对象
public class StaticFactory {
    public static IAccountService createAccountService(){
        return new AccountServiceImpl();
}

使用StaticFactory类中的静态方法createAccountService创建对象,涉及到标签的属性:

  • id属性: 指定对象在容器中的标识,用于从容器中获取对象
  • class属性: 指定静态工厂的全类名
  • factory-method属性: 指定生产对象的静态方法
<bean id="accountService"
      class="cn.maoritian.factory.StaticFactory"
      factory-method="createAccountService"></bean>

其实,类的构造函数也是静态方法,因此默认无参构造函数也可以看作一种静态工厂方法

7.2.3 使用实例工厂的方法创建对象

创建实例工厂如下:

public class InstanceFactory {
    public IAccountService createAccountService(){
        return new AccountServiceImpl();
    }
}

先创建实例工厂对象instanceFactory,通过调用其createAccountService()方法创建对象,涉及到标签的属性:

  • factory-bean属性: 指定实例工厂的id
  • factory-method属性: 指定实例工厂中生产对象的方法

<bean id="instancFactory"
      class="cn.maoritian.factory.InstanceFactory"></bean>
<bean id="accountService"
      factory-bean="instancFactory"
      factory-method="createAccountService"></bean>

八、使用注解实现IOC

8.1 用于创建对象的注解

这些注解的作用相当于bean.xml中的标签

  • @Component: 把当前类对象存入spring容器中,其属性如下:
    value: 用于指定当前类的 id. 不写时默认值是当前类名,且首字母改小写
  • @Controller: 将当前表现层对象存入spring容器中
  • @Service: 将当前业务层对象存入spring容器中
  • @Repository: 将当前持久层对象存入spring容器中
    @Controller,@Service,@Repository注解的作用和属性与@Component是一模一样的,可以相互替代,它们的作用是使三层对象的分别更加清晰.

8.2 用于注入数据的注解

这些注解的作用相当于bean.xml中的标签.

  1. @Autowired: 自动按照成员变量类型注入.
    注入过程
    • 当spring容器中有且只有一个对象的类型与要注入的类型相同时,注入该对象.
    • 当spring容器中有多个对象类型与要注入的类型相同时,使用要注入的变量名作为bean的id,在spring 容器查找,找到则注入该对象.找不到则报错.
      出现位置: 既可以在变量上,也可以在方法上
      细节: 使用注解注入时,set方法可以省略
  2. @Qualifier: 在自动按照类型注入的基础之上,再按照bean的id注入.
    出现位置: 既可以在变量上,也可以在方法上.注入变量时不能独立使用,必须和@Autowire一起使用; 注入方法时可以独立使用.
    属性:
    value: 指定bean的id
  3. @Resource: 直接按照bean的id注入,它可以独立使用.独立使用时相当于同时使用@Autowired和@Qualifier两个注解.
    属性:
    name: 指定bean的id
  4. @Value: 注入基本数据类型和String类型数据
    属性:
    value: 用于指定数据的值,可以使用el表达式(${表达式})

8.3 用于改变作用范围的注解

这些注解的作用相当于bean.xml中的标签的scope属性.

  • @Scope: 指定bean的作用范围
    属性:
    value: 用于指定作用范围的取值,“singleton”,“prototype”,“request”,“session”,“globalsession”

8.4 和生命周期相关的注解

这些注解的作用相当于bean.xml中的标签的init-method和destroy-method属性

  • @PostConstruct: 用于指定初始化方法
  • @PreDestroy: 用于指定销毁方法

九、Spring IoC 容器的设计

Spring IoC 容器的设计主要是基于以下两个接口:

  • BeanFactory
  • ApplicationContext

9.1、BeanFactory

在这里插入图片描述
从上图中我们可以几乎看到, BeanFactory 位于设计的最底层,它提供了 Spring IoC 最底层的设计,为此,我们先来看看该类中提供了哪些方法:
在这里插入图片描述
由于这个接口的重要性,所以有必要在这里作一下简短的说明:
【getBean】 对应了多个方法来获取配置给 Spring IoC 容器的 Bean。
① 按照类型拿 bean:
bean = (Bean) factory.getBean(Bean.class);
注意:要求在 Spring 中只配置了一个这种类型的实例,否则报错。(如果有多个那 Spring 就懵了,不知道该获取哪一个)
② 按照 bean 的名字拿 bean:
bean = (Bean) factory.getBean(“beanName”);
注意:这种方法不太安全,IDE 不会检查其安全性(关联性)
③ 按照名字和类型拿 bean:(推荐)
bean = (Bean) factory.getBean(“beanName”, Bean.class);
【isSingleton】 用于判断是否单例,如果判断为真,其意思是该 Bean 在容器中是作为一个唯一单例存在的。而【isPrototype】则相反,如果判断为真,意思是当你从容器中获取 Bean,容器就为你生成一个新的实例。
注意:在默认情况下,【isSingleton】为 ture,而【isPrototype】为 false

关于 type 的匹配,这是一个按 Java 类型匹配的方式
【getAliases】方法是获取别名的方法
这就是 Spring IoC 最底层的设计,所有关于 Spring IoC 的容器将会遵守它所定义的方法。

9.2、ApplicationContext

其中 ApplicationContext 是 BeanFactory 的子接口之一,换句话说:BeanFactory 是 Spring IoC 容器所定义的最底层接口,而 ApplicationContext 是其最高级接口之一,并对 BeanFactory 功能做了许多的扩展,所以在绝大部分的工作场景下,都会使用 ApplicationContext 作为 Spring IoC 容器。

  1. ApplicationContext的三个常用实现类:

    • ClassPathXmlApplicationContext: 它可以加载路径下的配置文件,要求配置文件必须在路径下,否则加载不了

      ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
      
    • FileSyetemXmlApplicationContext:它可以加载磁盘下任意路径下的配置文件(必须有访问权限)
      加载方式如下:

        ApplicationContext ac = new FileSystemXmlApplicationContext("C:\\user\\greyson\\...")
      
    • AnnotationConfigApplicationContext:它是用于读取注解创建容器的

  2. 核心容器的两个接口引发出来的问题

  • ApplicationContext:它在创建核心容器时,创建对象采取的策略是采用立即加载的方式,也就是说,只要一读取完配置文件就马上创建配置文件中配置的对象
    • 单例对象适用
    • 开发中常采用此接口
  • BeanFactory: 它在构建核心容器时,创建对象的策略是采用延迟加载的方式,什么时候获取 id 对象了,什么时候就创建对象。
    • 多例对象适用

9.3 Bean启动过程基本组件

9.3.1 BeanFactory

spring底层容器,定义了最基本的容器功能,注意区分FactoryBean。

  • BeanFactory
    BeanFactory是IOC最基本的容器,负责生产和管理bean,它为其他具体的IOC容器提供了最基本的规范,例如DefaultListableBeanFactory, XmlBeanFactory,ApplicationContext 等具体的容器都是实现了BeanFactory,再在其基础之上附加了其他的功能。

  • FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。要想获取FactoryBean的实现类,就要getBean(&BeanName),在BeanName之前加上&。

区别

BeanFactory和FactoryBean其实没有什么比较性的,只是两者的名称特别接近,所以有时候会拿出来比较一番,BeanFactory是提供了OC容器最基本的形式,给具体的IOC容器的实现提供了规范,FactoryBean可以说为IOC容器中Bean的实现提供了更加灵活的方式,FactoryBean在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式,我们可以在getObject()方法中灵活配置。其实在Spring源码中有很多FactoryBean的实现类,要想深入准确的理解FactoryBean,只有去读读Spring源码了。

9.3.2 ApplicationContext

扩展于BeanFactory,拥有更丰富的功能。例如:添加事件发布机制、父子级容器,一般都是直接使用ApplicationContext。

9.3.3 Resource

bean配置文件,一般为xml文件。可以理解为保存bean信息的文件。

9.3.4 BeanDefinition

beandifinition定义了bean的基本信息,根据它来创造bean

十、容器启动步骤

  1. 资源定位:找到配置文件
  2. BeanDefinition载入和解析
  3. BeanDefinition注册
  4. bean的实例化和依赖注入

10.1 BeanDefinition载入、解析、注册

  1. 找到配置文件Resource。
  2. 将配置文件解析成BeanDefinition
  3. 将BeanDefinition向Map中注册 Map<name,beandefinition>

通过上述三个步骤我们将配置在配置文件中的节点,全部封装到上述的Map<name,beandefinition>中。为后续的getBean()打下了基础。

这个过程大概可以理解为,

  1. 找到原材料
  2. 把原材料装进容器里

10.2 bean的实例化和依赖注入

注意: Bean 的定义和初始化在 Spring IoC 容器是两大步骤,它是先定义,然后初始化和依赖注入的。

10.3 Bean 的定义

Bean 的定义分为 3 步:

  1. Resource 定位 Spring IoC 容器先根据开发者的配置,进行资源的定位,在 Spring 的开发中,通过 XML 或者注解都是十分常见的方式,定位的内容是由开发者提供的。
  2. BeanDefinition 的载入 这个时候只是将 Resource 定位到的信息,保存到 Bean 定义(BeanDefinition)中,此时并不会创建 Bean 的实例
  3. BeanDefinition 的注册 这个过程就是将 BeanDefinition 的信息发布到 Spring IoC 容器中 注意:此时仍然没有对应的 Bean 的实例。

做完了以上 3 步,Bean 就在 Spring IoC 容器中被定义了,而没有被初始化,更没有完成依赖注入,也就是没有注入其配置的资源给 Bean,那么它还不能完全使用。

对于初始化和依赖注入,Spring Bean 还有一个配置选项——【lazy-init】,其含义就是是否初始化 Spring Bean。在没有任何配置的情况下,它的默认值为 default,实际值为 false,也就是 Spring IoC 默认会自动初始化 Bean。如果将其设置为 true,那么只有当我们使用 Spring IoC 容器的 getBean 方法获取它时,它才会进行 Bean 的初始化,完成依赖注入。

10.4 Bean的实例化和依赖注入

  1. 此过程由getBean()方法触发
  2. 创造 bean
  3. 完成 创建bean
  4. 实现依赖注入
  5. 最终创建bean, 根据bean定义,同时生成了注入属性,但值为null,还没注入属性对象。
  6. 填充属性,实现依赖注入,bean中的依赖bean是在这里注入的!

此过程根据上述的BeanDefition,

  1. 通过反射或者Cglib的方式创造bean
  2. 根据配置的依赖将所需要的bean注入进来,此过程会递归调用getBean()方法。
  3. 根据bean的scope决定是否缓存该Bean,一般情况为单例。容器会缓存该对象。

这个过程大概可以理解为

  • 将原材料进行加工,创造可以直接利用的产品。

到此,spring容器就可以对外提供服务了。

注意:
在分析 Spring Bean 实例化过程中提到 Spring 并不是一启动容器就开启 bean 的实例化进程,只有当客户端通过显示或者隐式的方式调用 BeanFactory 的 getBean() 方法来请求某个实例对象的时候,它才会触发相应 bean 的实例化进程,当然也可以选择直接使用 ApplicationContext 容器,因为该容器启动的时候会立刻调用注册到该容器所有 bean 定义的实例化方法。当然对于 BeanFactory 容器而言并不是所有的 getBean() 方法都会触发实例化进程,比如 signleton 类型的 bean,该类型的 bean 只会在第一次调用 getBean() 的时候才会触发,而后续的调用则会直接返回容器缓存中的实例对象。

10.5 总结

容器启动的过程可以分为2大步

  1. 获取、解析、注册配置信息,将配置的文件信息转换Map<name,beanDefinition>
  2. 根据上述的Map<name,beanDefinition>去实例化bean,并完成以来注入

11、spring的半注解配置和纯注解配置

spring的注解配置可以与xml配置并存,也可以只使用注解配置

11.1 半注解配置

在半注解配置下,spring容器仍然使用ClassPathXmlApplicationContext类从xml文件中读取IOC配置,同时在xml文件中告知spring创建容器时要扫描的包.

例如,使用半注解模式时,上述简单实例中的beans.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!--告知spring在创建容器时要扫描的包,配置此项所需标签不在beans的约束中,而在一个名为context的名称空间和约束中-->
    <context:component-scan base-package="cn.maoritian"></context:component-scan>
</beans>

然后将spring注解加在类的定义中.

11.2 纯注解配置

在纯注解配置下,我们用配置类替代bean.xml,spring容器使用AnnotationApplicationContext类从spring配置类中读取IOC配置

11.3 纯注解配置下的注解

  1. @Configuration: 用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解.获取容器时需要使用AnnotationApplicationContext(有@Configuration注解的类.class).
  2. @ComponentScan: 指定spring在初始化容器时要扫描的包,作用和bean.xml 文件中<context:component-scan base-package=“要扫描的包名”/>是一样的. 其属性如下:
    • basePackages: 用于指定要扫描的包,是value属性的别名
  3. @Bean: 该注解只能写在方法上,表明使用此方法创建一个对象,并放入spring容器,其属性如下:
    • name: 指定此方法创建出的bean对象的id
    • 细节: 使用注解配置方法时,如果方法有参数,Spring框架会到容器中查找有没有可用的bean对象,查找的方式与@Autowired注解时一样的.
  4. @PropertySource: 用于加载properties配置文件中的配置.例如配置数据源时,可以把连接数据库的信息写到properties配置文件中,就可以使用此注解指定properties配置文件的位置,其属性如下:
    • value: 用于指定properties文件位置.如果是在类路径下,需要写上"classpath:"
  5. @Import: 用于导入其他配置类.当我们使用@Import注解之后,有@Import注解的类就是父配置类,而导入的都是子配置类. 其属性如下:
    • value: 用于指定其他配置类的字节码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值