目录
一、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的作用范围和生命周期
- 单例对象: scope=“singleton”
- 作用范围: 每个应用只有一个该对象的实例,它的作用范围就是整个应用
- 生命周期: 单例对象的创建与销毁 和 容器的创建与销毁时机一致
- 对象出生: 当应用加载,创建容器时,对象就被创建
- 对象活着: 只要容器存在,对象一直活着
- 对象死亡: 当应用卸载,销毁容器时,对象就被销毁
- 多例对象: 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的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”
- 谁依赖于谁:是应用程序依赖于IoC容器;
- 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
- 谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
- 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。
5.2 依赖注入的方法
因为我们是通过反射的方式来创建属性对象的,而不是使用new关键字,因此我们要指定创建出对象各字段的取值.
5.2.1 使用构造函数注入
通过类默认的构造函数来给创建类的字段赋值,相当于调用类的构造方法.
涉及的标签: 用来定义构造函数的参数,其属性可大致分为两类:
- 寻找要赋值给的字段
- index: 指定参数在构造函数参数列表的索引位置
- type: 指定参数在构造函数中的数据类型
- name:指定参数在构造函数中的变量名,最常用的属性
- 指定赋给字段的值
- 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方法的成员. 其主要属性可大致分为两类:
- 指定要调用set方法赋值的成员字段
- name:要调用set方法赋值的成员字段
- 指定赋给字段的值
- 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字段:
六、使用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中的标签.
- @Autowired: 自动按照成员变量类型注入.
注入过程- 当spring容器中有且只有一个对象的类型与要注入的类型相同时,注入该对象.
- 当spring容器中有多个对象类型与要注入的类型相同时,使用要注入的变量名作为bean的id,在spring 容器查找,找到则注入该对象.找不到则报错.
出现位置: 既可以在变量上,也可以在方法上
细节: 使用注解注入时,set方法可以省略
- @Qualifier: 在自动按照类型注入的基础之上,再按照bean的id注入.
出现位置: 既可以在变量上,也可以在方法上.注入变量时不能独立使用,必须和@Autowire一起使用; 注入方法时可以独立使用.
属性:
value: 指定bean的id - @Resource: 直接按照bean的id注入,它可以独立使用.独立使用时相当于同时使用@Autowired和@Qualifier两个注解.
属性:
name: 指定bean的id - @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 容器。
-
ApplicationContext的三个常用实现类:
-
ClassPathXmlApplicationContext: 它可以加载路径下的配置文件,要求配置文件必须在路径下,否则加载不了
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
-
FileSyetemXmlApplicationContext:它可以加载磁盘下任意路径下的配置文件(必须有访问权限)
加载方式如下:ApplicationContext ac = new FileSystemXmlApplicationContext("C:\\user\\greyson\\...")
-
AnnotationConfigApplicationContext:它是用于读取注解创建容器的
-
-
核心容器的两个接口引发出来的问题
- 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
十、容器启动步骤
- 资源定位:找到配置文件
- BeanDefinition载入和解析
- BeanDefinition注册
- bean的实例化和依赖注入
10.1 BeanDefinition载入、解析、注册
- 找到配置文件Resource。
- 将配置文件解析成BeanDefinition
- 将BeanDefinition向Map中注册 Map<name,beandefinition>
通过上述三个步骤我们将配置在配置文件中的节点,全部封装到上述的Map<name,beandefinition>中。为后续的getBean()打下了基础。
这个过程大概可以理解为,
- 找到原材料
- 把原材料装进容器里
10.2 bean的实例化和依赖注入
注意: Bean 的定义和初始化在 Spring IoC 容器是两大步骤,它是先定义,然后初始化和依赖注入的。
10.3 Bean 的定义
Bean 的定义分为 3 步:
- Resource 定位 Spring IoC 容器先根据开发者的配置,进行资源的定位,在 Spring 的开发中,通过 XML 或者注解都是十分常见的方式,定位的内容是由开发者提供的。
- BeanDefinition 的载入 这个时候只是将 Resource 定位到的信息,保存到 Bean 定义(BeanDefinition)中,此时并不会创建 Bean 的实例
- 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的实例化和依赖注入
- 此过程由getBean()方法触发
- 创造 bean
- 完成 创建bean
- 实现依赖注入
- 最终创建bean, 根据bean定义,同时生成了注入属性,但值为null,还没注入属性对象。
- 填充属性,实现依赖注入,bean中的依赖bean是在这里注入的!
此过程根据上述的BeanDefition,
- 通过反射或者Cglib的方式创造bean
- 根据配置的依赖将所需要的bean注入进来,此过程会递归调用getBean()方法。
- 根据bean的scope决定是否缓存该Bean,一般情况为单例。容器会缓存该对象。
这个过程大概可以理解为
- 将原材料进行加工,创造可以直接利用的产品。
到此,spring容器就可以对外提供服务了。
注意:
在分析 Spring Bean 实例化过程中提到 Spring 并不是一启动容器就开启 bean 的实例化进程,只有当客户端通过显示或者隐式的方式调用 BeanFactory 的 getBean() 方法来请求某个实例对象的时候,它才会触发相应 bean 的实例化进程,当然也可以选择直接使用 ApplicationContext 容器,因为该容器启动的时候会立刻调用注册到该容器所有 bean 定义的实例化方法。当然对于 BeanFactory 容器而言并不是所有的 getBean() 方法都会触发实例化进程,比如 signleton 类型的 bean,该类型的 bean 只会在第一次调用 getBean() 的时候才会触发,而后续的调用则会直接返回容器缓存中的实例对象。
10.5 总结
容器启动的过程可以分为2大步
- 获取、解析、注册配置信息,将配置的文件信息转换Map<name,beanDefinition>
- 根据上述的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 纯注解配置下的注解
- @Configuration: 用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解.获取容器时需要使用AnnotationApplicationContext(有@Configuration注解的类.class).
- @ComponentScan: 指定spring在初始化容器时要扫描的包,作用和bean.xml 文件中<context:component-scan base-package=“要扫描的包名”/>是一样的. 其属性如下:
- basePackages: 用于指定要扫描的包,是value属性的别名
- @Bean: 该注解只能写在方法上,表明使用此方法创建一个对象,并放入spring容器,其属性如下:
- name: 指定此方法创建出的bean对象的id
- 细节: 使用注解配置方法时,如果方法有参数,Spring框架会到容器中查找有没有可用的bean对象,查找的方式与@Autowired注解时一样的.
- @PropertySource: 用于加载properties配置文件中的配置.例如配置数据源时,可以把连接数据库的信息写到properties配置文件中,就可以使用此注解指定properties配置文件的位置,其属性如下:
- value: 用于指定properties文件位置.如果是在类路径下,需要写上"classpath:"
- @Import: 用于导入其他配置类.当我们使用@Import注解之后,有@Import注解的类就是父配置类,而导入的都是子配置类. 其属性如下:
- value: 用于指定其他配置类的字节码