1. IOC 和 DI
IOC(Inversion of Control,即 控制反转)
- 控制:IOC容器控制对象的创建及外部资源的获取
- 反转:由主动new依赖对象的方式转变为被动获取IOC容器提供的对象实例
DI(Dependency Injection,即 依赖注入)
- 依赖:对象依赖IOC容器来配置自身
- 注入:IOC容器把外部资源注入到对象
IOC 和 DI 是同一概念的不同表达方式,可以把IOC容器看作是一个加工厂,这个工厂里要生产的对象都在配置文件(设计图纸)中给出定义,然后利用反射原理,根据配置文件中给出的类名生成相应的对象
2. Spring核心容器(Core Container)
- Core:使用了 IOC 设计思想提供了 DI 功能
- Beans:提供了 BeanFactory ,是一个管理 bean 的工厂
- Context:提供了 ApplicationContext 核心接口
- Expression:提供了一种在运行时操作对象的表达式语言
2.1 BeanFactory(基础容器)
BeanFactory 接口定义了管理 bean 的最基本方法,如 getBean()、getType()等
BeanFactory 有多个子接口,扩展了与 bean 相关的功能,其中:
- HierarchicalBeanFactory:扩展实现了 bean 工厂的分层
- ListableBeanFactory:扩展实现了根据条件返回 bean 集合的功能
2.2 ApplicationContext(高级容器)
ApplicationContext 是 BeanFactory 的子接口,在其基础上提供了其他高级特性
3. Spring配置 bean
3.1 基于 xml 文件
<bean id="person" class="com.codfish.beans.Person">
<property name="name" value="张三"></property>
<property name="age" value="28"></property>
</bean>
bean 标签常用属性:
- class:bean的限定类名,指向classpath下类定义的所在位置
- id/name:bean的唯一标识名,规范是小写字母开头驼峰式
- scope:bean的作用域,singleton、prototype、request、session
- init-method:创建bean后调用该方法
- destroy-method:销毁bean前调用该方法释放资源
- autowire:bean的自动装配,byName、byType、constructor
bean 常用子标签:
- property:注入成员变量
- constructor-arg:注入构造器参数,可由name或index下标指定目标参数
依赖注入:
(1)set 方法注入(常用)
public class UserService implements IUserService {
private IUserDao userDao;
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
}
<bean id="userService" class="com.codfish.dao.UserService">
<property name="userDao" ref="userDaoMybatis"></property>
</bean>
<bean id="userDaoMybatis" class="com.codfish.dao.UserDaoMybatis"></bean>
(2)构造方法注入
public class UserService implements IUserService {
private IUserDao userDao;
public UserService(IUserDao userDao) {
this.userDao = userDao;
}
}
<bean id="userService" class="com.codfish.dao.UserService">
<constructor-args name="userDao" ref="userDaoMybatis"></constructor-args>
</bean>
<bean id="userDaoMybatis" class="com.codfish.dao.UserDaoMybatis"></bean>
项目中一般使用set方法注入,因为它不会改变类的构造方法
3.2 基于注解
package com.codfish.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import javax.sql.DataSource;
@Configuration
@ComponentScan("com.codfish") //扫描包
@PropertySource("classpath:druid-config.properties") //Source配置文件
public class SpringConfig {
@Value("${jdbc.driverClassName}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource){
return new QueryRunner(dataSource);
}
@Bean
public DataSource createDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
- @Configuration:相当于标签里的beans,bean都在此注解下创建
- @Bean:在方法上声明,表示创建一个bean对象交给Spring管理,并调用一次该方法,bean的默认id为类名首字母小写
注解注入
- @Component:注册所有bean (全部用这个就行)
- @Repository:注册持久层bean
- @Controller:注册控制层bean
- @Service:注册业务层bean
@Component 和 @Bean 注册 bean 的区别:
- @Component 作用于类,为这个类创建 bean(不推荐加在接口上)
- @Bean 作用于方法,将返回的对象创建为 bean
从 IOC 容器获取对象:
自动装配
- @Resource:属于J2EE的注解,默认 byName 匹配
- @Autowired:属于Spring的注解,默认 byType 匹配
用 getbean() 获取
参数首先要用接口类,如果没有接口,再用本类
//要获取的类实现了接口,说明从IOC容器获取的对象是其JDK代理对象
Interface bean = ioc.getBean(Interface.class);
//没接口的类,从IOC容器获取的对象是基于子类的CGlib代理对象
Class bean = ioc.getBean(Class.class);