底层实现原理
工厂+反射+配置文件
IOC和DI
控制反转(Inversion of Control),简称IOC;依赖注入(Dependency Injection),简称DI。其实他们是对同一概念的不同角度的描述。
- IOC是一种设计思想,举个鲜明的例子,传统的应用程序在类内部创建依赖对象,就像是我们直接找女朋友;有了IOC容器后,由容器创建和查找相应的依赖对象并注入,就像是有了婚介所,由婚介所根据我们的要求推荐给我们适合的对象。
- 在Spring中,对象无需自己查找或创建与其所关联的其他对象。相反,容器负责把需要相互协作的对象引用赋予各个对象。
- IOC将原本在程序中创建对象的控制权交给Spring框架管理,这就是控制反转。
- 属性通过Spring配置文件写入,这就是依赖注入。
- Spring通过反射来实现程序运行中动态向某个对象提供其依赖的其他对象。
使用Spring装配bean
创建应用对象之间协作关系的行为通常称为装配(wiring),这也是依赖注入的本质。以下介绍配置Spring容器的三种方式。
1.基于注解方式装配bean
使用组件扫描(默认不开启)和自动装配实现Spring的自动化配置。
- 开启组件扫描的方式
- 使用XML来启用组件扫描,可以使用Spring context命名空间的
<context:component-scan>
元素,其含有base-package属性 - 使用Java配置类启用组件扫描,使用@ComponentScan注解
- 使用XML来启用组件扫描,可以使用Spring context命名空间的
- 相关注解:
- @Component,在类上添加此注解,表明该类会作为组件类,并告知Spring要为这个类创建bean。不常用,推荐使用以下注解代替:
- @Controller,应用在表现层
- @Service,应用在业务层
- @Repository,应用在数据访问层
- @ComponentScan,在配置类上添加此注解,表明启用组件扫描,查找带有@Component注解的类。默认Spring会扫描与配置类相同的包,
- @Autowired,同@Inject注解,在构造器或者setter方法或其他需要的方法上添加此注解,声明要进行自动装配,自动装配时在Spring应用上下文中寻找匹配某个bean需求的其他bean。
- @Resource,@AutoWired、@Qualifier 都用来注入对象。其中@Resource可以以 name(默认) 或 type 方式注入,@AutoWired只能以 type 方式注入,@Qualifier 只能以 name 方式注入。@Resources是JDK提供的注解,而@Autowired是Spring提供的注解。推荐以名称方式注入,因为按类型注入,如果不同包内有同名的类会报错找不到。
- @Component,在类上添加此注解,表明该类会作为组件类,并告知Spring要为这个类创建bean。不常用,推荐使用以下注解代替:
- 为组件扫描的bean命名
Spring应用上下文中所有的bean都会给定一个ID,默认将类名的第一个字母变为小写作为ID。有三种方式命名:- 通过@ComponentScan的value属性中指明包的名称(同@Named注解)
- 通过basePackages属性进行配置多个基础包,使用String类型配置,不安全
- 更安全一些,使用basePackageClasses属性设置组件类。
2.基于Java方式装配bean
有时不能使用自动化配置,比如装配第三方库中的组件到你的应用中,这时可以考虑显式配置。在进行显式配置时,有两种可选方案: Java和XML。JavaConfig是更好的方案,因为它更为强大、类型安全并且对重构友好。具体步骤如下:
- 创建配置类
在类上添加@Configuration注解来表明这是配置类。 - 声明简单的bean
在方法上添加@Bean注解,告诉Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文中的bean。方法体中包含了最终产生bean实例的逻辑。
默认情况下,bean的ID与带有@Bean注解的方法名是一样的,重命名可以使用name属性。 - 初始化bean
声明bean的方法需要创建并返回bean。默认情况下,Spring中的bean都是单例的。返回的对象可以使用其他的bean,使用构造器方法或者setter方法或者对象引用作为参数来产生需要返回的bean。
3.基于XML文件方式装配bean
推荐使用前两种方案来配置Spring,使用xml来维护已有的XML配置。创建和管理Spring XML配置文件可以使用Spring Tool Suite工具。使用步骤如下:
- 创建XML文件
在Spring Tool Suite的菜单中,选 择File>New>Spring Bean Configuration File,能够创建Spring XML配置文件,并且可以选择可用的配置命名空间。 - 声明一个简单的bean
使用<bean>
元素声明一个bean,类似于@Bean注解。当Spring发现这个<bean>
元素时,它将会调用类的默认构造器来创建bean。而在JavaConfig配置方式中,可以自由选择一个方法进行配置。这是xml配置的一个缺点。
在class属性中使用全限定域名指定创建这个bean的类,最好使用id属性来命名而不是默认命名。bean的类型使用字符串的形式设置在了class属性中,有时我们不能保证设置给class属性的值是真正的类,比如修改了类名,这是xml配置的另一个缺点。 - 初始化bean
- 使用构造器注入方法,有两种方案:
- 使用
<constructor-arg>
元素
使用ref属性引用其他bean的ID;
使用value属性引用字面量;
使用<list>
子元素下的<value>
或<ref>
子元素来注入集合,这里list为对应的集合 - 使用Spring 3.0所引入的c-命名空间(需要在xml头部引入c命名空间及其模式)
在<bean>
元素中使用c:cd-ref属性引用其他bean;
使用c:cd属性引用字面量;(cd为构造器参数名,可以换成参数索引_n)
- 使用
- 使用setter注入方法
- 使用
<property>
元素为属性的setter方法所提供的功能与<constructor-arg>
元素为构造器所提供的功能是一样的。 - 使用p-命名空间(需要在xml头部引入p命名空间及其模式),p-命名空间中属性所遵循的命名约定与c-命名空间中的属性类似。
使用Spring util-命名空间(需要在xml头部引入util-命名空间及其模式)的<util:list>
元素及其<value>
子元素来引入集合
- 使用
- 使用构造器注入方法,有两种方案:
使用Spring获取bean
1.通过xml文件获取
AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
((Tom) context.getBean("tom")).say();
context.close();
2.通过配置类获取
AbstractApplicationContext context2 = new AnnotationConfigApplicationContext(AppConfig.class);
((Jerry) context2.getBean("jerry")).say();
context2.close();
Spring IOC实战测试
- 创建普通Java项目,将以下几个基本jar包复制到src目录下,选中jar包右键-Build Path-Add to Build Path。
- 测试配置类装配bean
- 创建Java类
- 使用@Configuration注解创建配置类
- 使用@Bean注解在配置类中装配bean
- 或者使用@ComponentScan开启注解扫描并在Java类中使用@Component注解声明为组件类来装配bean
- 创建测试类,通过配置类获取bean,调用类的方法
- 测试xml文件装配bean
- 创建Java类
- 创建xml文件,并开启组件扫描;使用bean标签装配bean
- 创建测试类,通过xml文件获取bean,调用类的方法