Spring4——IOC/DI
来源:互联网 发布:apache 开启https 编辑:程序博客网 时间:2024/05/22 02:25
1 Spring概述
- 轻量级:Spring是非侵入性的——基于Spring的开发不需要实现Spring的接口,不用继承任何父类
- 依赖注入(Dependancy Injection, DI),或反转控制(Inversion of Control, IOC)
- 面向切面编程(AOP——Aspect Oriented Programming)
- 容器:Spring是一个容器,因为它包含并且管理应用对象的生命周期
- 框架:Spring实现了使用简单的组件配置组合成一个复杂的应用,在Spring中可以使用XML和Java注解组合这些对象
- 一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库
2 IOC和DI
IOC的思想是反转资源获取的方向。容器主动地将资源推送给它所管理的组件,组件所要做的仅是选择一种合适的方式来接受资源。
DI——IOC的另一种表述方式:组件以一些预先设定好的方式(如setter方法)接受来自如容器的资源注入。
3 配置bean:
3.1 基于XML文件的方式配置bean
① 配置形式:基于XML文件的方式;基于注解的方式
② Bean的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法&实例工厂方法)、FactoryBean
③ IOC容器:ApplicationContext
- ApplicationContext的主要实现类:ClassPathXmlApplicationContext:从类路径下加载配置文件,以及FileSystemXmlApplicationContext:从文件系统中加载配置文件。
- ConfigurableApplicationContext扩展于ApplicationContext,新增两个主要方法:refresh()和close(),让ApplicationContext具有启动、刷新和关闭上下文的功能。
- ApplicationContext在初始化上下文时就实例化所有单例Bean。
- WebApplicationContext是专门为WEB应用而准备的,它允许从相对于WEB根目录的路径中完成初始化工作。
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
④ 依赖注入的方式:属性注入,构造器注入
属性注入:
- 属性注入即通过setter方法注入bean的属性值或依赖的对象
- 属性注入使用
<property>
元素,使用name属性指定Bean的属性名称,value属性或<value>
子节点指定属性值 - 属性注入是实际应用中最常用的注入方式。
<bean id="helloWorld" class="com.zc.spring.beans.HelloWorld"> <property name="name" value="Spring"></property> </bean>
构造方法注入:
- 通过构造方法注入Bean的属性值或依赖的对象,它保证了Bean实例在实例化后可以使用。
- 构造器注入在
<constructor-arg>
元素里声明属性,<constructor-arg>
中没有name属性。
<!-- 使用构造器注入属性值可以指定参数的位置和参数的类型,以区分重载的构造方法--> <bean id="car" class="com.zc.spring.beans.Car"> <constructor-arg value="Audi" index="0"></constructor-arg> <constructor-arg index="1"> <!--如果字面值包含特殊字符可以使用<![CDATA[]]> 包裹起来--> <!--属性值也可以使用value子节点进行配置--> <value><![CDATA[<ShangHai^>]]></value> </constructor-arg> <constructor-arg type="double"> <value>3000</value> </constructor-arg> </bean> <bean id="car2" class="com.zc.spring.beans.Car"> <constructor-arg value="Baoma" type = "java.lang.String"></constructor-arg> <constructor-arg value="Shanghai" type="java.lang.String" ></constructor-arg> <constructor-arg value="200" type="int"></constructor-arg> </bean>
引用其他Bean:组成应用程序的Bean经常需要相互协作以完成应用程序的功能。在Bean的配置文件中,通过<ref>
或ref属性为Bean的属性或构造器参数指定对Bean的引用,使得Bean能够互相访问。也可以在属性或构造器里包含Bean的声明,这样的Bean成为内部Bean。
内部Bean:当Bean实例仅仅给一个特定的属性使用时,可以将其声明为内部Bean。内部Bean声明直接包含在< property>或< constructor-arg>元素里,不需要设置任何id或name属性。内部Bean不能使用在其他任何地方。
<bean id="person" class="com.zc.spring.beans.Person"> <property name="name" value="Tom"></property> <property name="age" value="18"></property> <!--使用property的ref属性建立bean之间的引用关系--> <!-- <property name="car" ref="car2"></property> --> <!--使用<ref>子节点或ref属性都可以 <property name="car"> <ref bean = "car2" /> </property> --> <!--内部bean,不能被外部引用,只能在内部使用--> <property name="car"> <bean class="com.zc.spring.beans.Car"> <constructor-arg value="Ford"></constructor-arg> <constructor-arg value="Changan"></constructor-arg> <constructor-arg value="200000" type="double"></constructor-arg> </bean> </property> </bean> <bean id="person2" class="com.zc.spring.beans.Person"> <constructor-arg value="Jerry"></constructor-arg> <constructor-arg value="25"></constructor-arg> <constructor-arg ref="car"></constructor-arg> </bean>
3.2 基于注解的方式配置bean
① 在classpath中扫描组件
- 组件扫描(component scanning):Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件。
- 特定组件包括:
-@Component:基本注解,标识一个受Spring管理的组件
-@Respository:标识持久层组件
-@Service:标识业务层组件
-@Controller:标识表现层组件 - 对于扫描到的组件,Spring有默认的命名策略:其一,使用非限定类名(UserService),第一个字母小写(userService);其二,也可以在注解中通过value属性值标识组件的名称,如UserService是一个接口,可以将接口的实现类UserServiceImpl通过value标识为userService。
Component部分:
package com.zc.spring.beans.annotation;import org.springframework.stereotype.Component;@Componentpublic class TestObject {}
Repository部分:
UserRepository接口:
package com.zc.spring.beans.annotation.repository;public interface UserRepository { void save();}
UserRepositoryImpl接口实现类:
package com.zc.spring.beans.annotation.repository;import org.springframework.stereotype.Repository;@Repository("userRepository")public class UserRepositoryImpl implements UserRepository { @Override public void save() { System.out.println("UserRepository save..."); }}
Service部分:
package com.zc.spring.beans.annotation.service;import org.springframework.stereotype.Service;@Servicepublic class UserService { public void add(){ System.out.println("UserService add..."); }}
Contoller部分:
package com.zc.spring.beans.annotation.controller;import org.springframework.stereotype.Controller;@Controllerpublic class UserController { public void execute(){ System.out.println("UserController execute "); }}
在组件类上使用了特定的注解之后,还需要在Spring的配置文件中声明
<context:component-scan>
:-base-packge属性制定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类。
-当需要扫描多个包时,可以使用逗号分隔。
beans-annotation.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"> <!--指定Srping IOC容器扫描的包--> <context:component-scan base-package="com.zc.spring.beans.annotation"></context:component-scan></beans>
以上,测试类为:
package com.zc.spring.beans.annotation;import com.zc.spring.beans.annotation.controller.UserController;import com.zc.spring.beans.annotation.repository.UserRepository;import com.zc.spring.beans.annotation.service.UserService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main { public static void main(String[] args){ ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml"); TestObject to = (TestObject) ctx.getBean("testObject"); System.out.println(to); UserController userController = (UserController) ctx.getBean("userController"); System.out.println(userController); UserService userService = (UserService) ctx.getBean("userService"); System.out.println(userService); UserRepository userRepository = (UserRepository)ctx.getBean("userRepository"); System.out.println(userRepository); }}
测试结果:通过注解配置了4个bean,分别打印出来。
如果仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类,如:
<context:component-scan base-package="com.zc.spring.beans.annotation" resource-pattern="repository/*.class"></context:component-scan>
- 子节点
context:include-filter
标识要包含的目标类,该子节点需要use-default-filters="false"
(不使用默认的过滤器)来配合使用
<context:component-scan base-package="com.zc.spring.beans.annotation" use-default-filters="false"> <!--<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"></context:include-filter>--> <context:include-filter type="assignable" expression="com.zc.spring.beans.annotation.repository.UserRepository"></context:include-filter></context:component-scan>
- context:exclude-filter 子节点指定排除哪些指定表达式的组件
<context:component-scan base-package="com.zc.spring.beans.annotation"> <!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"></context:exclude-filter>--> <context:exclude-filter type="assignable" expression="com.zc.spring.beans.annotation.repository.UserRepository"></context:exclude-filter></context:component-scan>
过滤表达式中type="annotation"
表示过滤所有标注了expression表达式表明的类,type="assignable"
表示过滤所有继承或扩展expression表达式表明的类。
当Bean和Bean之间有关联关系时
- 使用@Autowired注解自动装配具有兼容类型的单个Bean 属性如构造方法,普通字段(即使是非public),一切具有参数的方法都可以应用,如:
package com.zc.spring.beans.annotation.controller;import com.zc.spring.beans.annotation.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;@Controllerpublic class UserController { //UserController和UserService有关联 @Autowired private UserService userService; public void execute(){ System.out.println("UserController execute "); userService.add(); }}
- 默认情况下,所有使用@Autowired注解的属性都需要被设置。当Spring找不到匹配的Bean装配属性时,会抛出异常,若某一属性允许不被设置,可以设置@Autowired注解的required属性为false。
若TestObject类为:
package com.zc.spring.beans.annotation;import org.springframework.stereotype.Component;//此处没有注解public class TestObject {}
则
package com.zc.spring.beans.annotation.repository;import com.zc.spring.beans.annotation.TestObject;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Repository;@Repository("userRepository")public class UserRepositoryImpl implements UserRepository { //设置required=false @Autowired(required = false) private TestObject testObject; @Override public void save() { System.out.println("UserRepository save..."); System.out.println(testObject); }}
测试类:
package com.zc.spring.beans.annotation;import com.zc.spring.beans.annotation.repository.UserRepository;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main { public static void main(String[] args){ ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml"); UserRepository userRepository = (UserRepository)ctx.getBean("userRepository"); userRepository.save(); }}
结果:
- 默认情况下,当IOC容器存在多个类型兼容的Bean时(如一个接口有多个实现类),通过类型的自动装配将无法工作。此时,除了在注解中通过value属性值标识组件的名称外,还可以在@Qualifier注解里提供Bean的名称,Spring允许对方法的入参标注@Qualifier以指定注入Bean的名称。
import com.zc.spring.beans.annotation.repository.UserRepository;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Service;@Servicepublic class UserService { @Autowired @Qualifier("userRepositoryImpl") private UserRepository userRepository;//此时接口userRepository有多个实现类 public void add(){ System.out.println("UserService add..."); userRepository.save(); }}
或者
package com.zc.spring.beans.annotation.service;import com.zc.spring.beans.annotation.repository.UserRepository;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Service;@Servicepublic class UserService { private UserRepository userRepository; @Autowired public void setUserRepository(@Qualifier("userRepositoryImpl") UserRepository userRepository) { this.userRepository = userRepository; } public void add(){ System.out.println("UserService add..."); userRepository.save(); }}
- Spring4——IOC/DI
- Spring4 之 IOC & DI
- Spring4的IoC和DI的区别
- Spring4的IoC和DI的区别
- Spring4学习笔记(二):IOC&DI概述
- Spring4.3x教程之一IOC&DI
- Spring4的IoC和DI的区别
- Spring学习总结 —— IoC/DI
- Spring——IOC/DI理解
- Spring框架——IOC&DI
- Spring4 学习笔记(2)-介绍 IOC 和 DI
- Spring4 学习笔记(2)-介绍 IOC 和 DI
- 4.Spring4.x学习[核心篇][IOC/DI简介以及Spring中IOC的方式介绍]
- 依赖注入那些事儿——DI与IoC
- Spring IoC和DI——学习笔记
- Spring 核心技术——IoC 之 DI (1)
- Spring 核心技术——IoC 之 DI (2)
- Spring核心之一——Ioc/DI(一)
- java 并发包
- jq获取当前鼠标坐标
- 两个只出现一次的数字。
- 提交方式
- Codeforces 735D Taxes
- Spring4——IOC/DI
- Cocos2d-x《雷电大战》(3)-子弹无限发射
- LeetCode刷题【Array】 Maximum Product of Three Numbers
- Oracle学习笔记(五)
- 测试
- Mysql 分组聚合实现 over partition by 功能
- Android面试复习(Android篇三)
- HDU-4609 3-idiots(FFT)
- KL距离(相对熵)