IOC作用:降低程序的耦合(依赖关系)
例子:
1、创建maven工程,在pom.xml里引入dependency
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency>2、在resource下创建bean.xml(配置Spring用来反射查找的类)
<?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"> <!--把对象的创建交给spring管理,spring通过自定义的id获取你的class--> <!--创建bean的方式:--> <!--方式一:只定义了id和class的属性时,默认通过该class的构造函数创建对象,若该class没有构造函数,则无法创建--> <bean id="accountService" class="com.kunjava.service.impl.AccountServiceImpl"></bean> <!--方式二:使用普通工厂的方法创建对象并存入容器--> <!-- <bean id="factory" class="com.kunjava.factory.InstanceFactory"></bean>--> <!-- <bean id="accountService" factory-bean="factory" factory-method="getAccountService"></bean>--> <!--方式三:使用工厂的静态方法创建对象并存入容器--> <!-- <bean id="accountService" class="com.kunjava.factory.StaticFactory" factory-method="getAccountService"></bean>--> </beans>补充:
bean标签的scope属性:指定bean的作用范围
singletonprototyperequestsessionglobal-session单例(常用)多例(常用)作用于Web应用的请求范围作用于Web应用的请求范围作用于集群的全局会话范围
bean对象的生命周期
单例对象(scope=singleton)多例对象(scope=prototype)出生容器创建时对象使用时活着容器生,对象生一直活着死亡容器销毁,对象销毁由Java垃圾回收器回收
3、通过bean.xml配置获取Spring的IOC容器,根据id获取对象
public static void main(String[] args) { //1、获取容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); //(PS:当加载完配置文件时会立刻创建配置文件对应的对象,可通过构造函数测试) //2、根据id获取对象 IAccountService as = ac.getBean("accountService",IAccountService.class); System.out.println(as);//com.kunjava.service.impl.AccountServiceImpl@971d0d8 }补充:
常用的容器有三种:
ClassPathXmlApplicationContext: 加载类的根路径下配置文件FileSystemXmlApplicationContext: 加载磁盘路径上配置文件AnnotationConfigApplicationContext: 读取注解创建容器
Spring还提供另一种IoC容器叫BeanFactory,使用方式和ApplicationContext类似:
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("bean.xml")); IAccountService as = factory.getBean("accountService",IAccountService.class);BeanFactory和ApplicationContext的区别
BeanFactory的实现是按需创建,即第一次获取Bean时才创建这个Bean
ApplicationContext会一次性创建所有的Bean(实际上,ApplicationContext接口是从BeanFactory接口继承而来的)
控制反转IoC(Inversion of Control):将创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到了第三方。
依赖注入(Dependency Injection):动态的向某个对象提供它所依赖的其他对象资源(例如:BeanA依赖BeanB,SpingIOC通过配置创建BeanB的实例,并通过某种方式注入到BeanA)
注入方式:
● 基于构造函数的依赖注入
部分代码示例:
private String name; private Integer age; private Date date; public AccountServiceImpl(String name, Integer age, Date date) { this.name = name; this.age = age; this.date = date; } <!-- 方式一:通过构造函数注入--> <bean id="accountService" class="com.kunjava.service.impl.AccountServiceImpl"> <constructor-arg name="name" value="明"></constructor-arg> <constructor-arg name="age" value="24"></constructor-arg> <constructor-arg name="date" ref="now"></constructor-arg> </bean> <bean id="now" class="java.util.Date"></bean>● 基于set的依赖注入
部分代码示例:
private String name; private Integer age; private List list; private Map map; public void setName(String name) { this.name = name; } public void setAge(Integer age) { this.age = age; } public void setList(List list) { this.list = list; } public void setMap(Map map) { this.map = map; } <!-- 通过set注入--> <bean id="accountService1" class="com.kunjava.service.impl.AccountServiceImpl1">--> <property name="name" value="明"></property> <property name="age" value="23"></property> <property name="list"> <array> <value>list1</value> <value>list2</value> <value>list3</value> </array> </property> <property name="map"> <map> <entry key="mapkey1"> <value>map1</value> </entry> <entry key="mapkey2"> <value>map2</value> </entry> <entry key="mapkey3"> <value>map3</value> </entry> </map> </property> </bean>● 基于注解的依赖注入
对比XML配置方式注解方式用于创建对象<bean id=‘’ class=‘’></bean>@Component,不写value时默认为当前类名,首字母小写
也可用@Controller,@Service,@Repository分别表示表现层,业务层,持久层
用于注入数据property属性标签
(可以注入基本类型,String类型,集合类型以及其他自定义的bean类型)
@Autowired,自动按类型注入(条件:在Ioc容器中有bean对象和要注入的变量或方法的类型一致)
@Qualifier,在类中注入基础上按名称注入,给类成员注入时不能独立使用,要依托于@Autowired,给方法参数注入时可用
@Resource(name=""),可以直接注入类的id
(以上方式只能注入其他bean类型,无法注入基本类型,String类型以及集合类型)
用于作用范围scope属性(singleton,prototype,...)@Scope,不写value时默认为singleton生命周期相关
init-method,指定初始化方法。
destory-method,指定销毁方法
@PostConstruct,指定初始化方法
@PreDestory,指定销毁方法
(与bean对象的作用范围有关)
部分代码示例:
<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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 告知spring在创建对象时要扫描的包,通过context标签进行配置和约束--> <context:component-scan base-package="com.kunjava"></context:component-scan> </beans> //注解方式 @Component(value = "accountService")//value=可不写 @Scope()//作用范围,默认为单例 public class AccountServiceImpl implements IAccountService { // @Autowired // @Qualifier("accountDao1") @Resource(name = "accountDao1") private IAccountDao accountDao; public void saveAccount(){ accountDao.saveAccount(); } } @Repository("accountDao1") public class IAccountDaoImpl1 implements IAccountDao { public void saveAccount(){ System.out.println("保存了账户1111111"); } } //1、创建ioc容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); //2、根据id获取对象 IAccountService as = ac.getBean("accountService",IAccountService.class); IAccountService as1 = ac.getBean("accountService",IAccountService.class); System.out.println(as == as2);//true as.saveAccount();