查看“Spring:IOC”的源代码
←
Spring:IOC
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:SpringFramework]] == 关于IOC == IOC:Inversion of Control '''控制反转''',指的是'''对象的创建权反转(交给)给Spring''',作用是实现了程序的解耦合。 [[File:IOC 的底层实现原理.jpg|1000px]] 下载: * 官网:“http://spring.io/” * 下载地址:“http://repo.springsource.org/libs-release-local/org/springframework/spring” Spring 目录结构: * docs:API 和开发规范 * libs:jar 包和源码 * schema:约束 相关jar: :[[File:IOC相关jar包.jpg|400px]] : 即“core container”的四个部分; :[[File:SpringFramework Runtime.jpg|600px]] == 使用示例 == # 创建web 项目 # 引入Spring 的开发包 # 相关配置文件: ## log4j.properties:日志配置 ## applicationContext.xml:Spring配置文件: ##* (配置说明,位于包的doc中:“spring-framework-4.2.4.RELEASE\docs\spring-framework-reference\html\xsd-configuration.html”) ##: <syntaxhighlight lang="xml"> <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 http://www.springframework.org/schema/beans/spring-beans.xsd"> </beans> </syntaxhighlight> # 编写相关的类: #: <syntaxhighlight lang="java"> public interface UserDao { public void sayHello(); } public class UserDaoImpl implements UserDao { @Override public void sayHello() { System.out.println("Hello Spring..."); } } </syntaxhighlight> # 完成配置: #: <syntaxhighlight lang="xml"> <!-- Spring 的入门案例 --> <bean id="userDao" class="cn.itcast.spring.demo1.UserDaoImpl"></bean> </syntaxhighlight> # 编写测试程序: #: <syntaxhighlight lang="java"> @Test // Spring 的方式: public void demo2(){ // 创建Spring 的工厂类: ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); // 通过工厂解析XML 获取Bean 的实例. UserDao userDao = (UserDao) applicationContext.getBean("userDao"); userDao.sayHello(); } </syntaxhighlight> == Spring 中的工厂 == * BeanFactory :是在getBean 的时候才会生成类的实例. * ApplicationContext :在加载applicationContext.xml 时候就会创建. === ApplicationContext === ApplicatioContext 接口有两个实现类: # “ClassPathXmlApplicationContext”:加载类路径下Spring 的配置文件; # “FileSystemXmlApplicationContext”:加载本地磁盘下Spring 的配置文件; [[File:ApplicatioContext 接口的两个实现类.jpg|500px]] === BeanFactory === [[File:Spring的工厂.jpg|700px]] == Spring 的相关配置 == * 分配置文件,实现的两种方法: *# 加载多个配置文件: *#: <syntaxhighlight lang="java"> ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext2.xml"); </syntaxhighlight> *# 在主配置文件(“applicationContext.xml”)中包含其他配置文件,如: *#: <syntaxhighlight lang="properties"> <import resource="applicationContext2.xml"></import> </syntaxhighlight> == Bean的管理:XML == === 相关配置 === ---- * '''id''':唯一确定一个Bean(唯一性约束),必须以字母开始,可以使用字母、数字、连字符、下划线、句点、冒号,不能出现特殊字符; * '''name''':Bean的名称(没有唯一性约束),name可以使用特殊字符;如果<bean>没有id 的话, name 可以当做id 使用; * '''class''':类的全路径名称; ** 整合struts1 的时候:“<bean name=”/loginAction” >”; * '''scope''':Bean 的作用范围; ** “'''singleton'''”:(默认)单例; ** “prototype”:多例; ** “request”:WEB 项目中,Spring 创建一个Bean 的对象,将对象存入到request 域中; ** “session”:WEB 项目中,Spring 创建一个Bean 的对象,将对象存入到session 域中; ** “globalSession”:WEB 项目中,应用在Porlet 环境.如果没有Porlet 环境那么globalSession 相当于session; * '''Bean 的生命周期'''的配置:通过配置<bean>标签上的“init-method”作为Bean 的初始化的时候执行的方法,配置“destroy-method”作为Bean 的销毁的时候执行的方法。 ** 销毁方法想要执行,需要是单例创建的Bean;而且在工厂关闭的时候,Bean 才会被销毁. === Bean实例化的三种方式 === ---- # '''使用类的无参数构造创建'''(重点) #: <syntaxhighlight lang="properties"> <!-- 方式一:无参数的构造方法的实例化--> <bean id="bean1" class="cn.itcast.spring.demo3.Bean1"></bean> </syntaxhighlight> # 使用静态工厂创建: #: <syntaxhighlight lang="java"> // 提供一个工厂类 public class Bean2Factory { public static Bean2 getBean2(){ return new Bean2(); } } </syntaxhighlight> #: <syntaxhighlight lang="properties"> <!-- 方式二:静态工厂实例化Bean --> <bean id="bean2" class="cn.itcast.spring.demo3.Bean2Factory" factory-method="getBean2"/> </syntaxhighlight> # 使用实例工厂创建 #: <syntaxhighlight lang="java"> // 提供Bean3 的实例工厂: public class Bean3Factory { public Bean3 getBean3(){ return new Bean3(); } } </syntaxhighlight> #: <syntaxhighlight lang="properties"> <!-- 方式三:实例工厂实例化Bean --> <bean id="bean3Factory" class="cn.itcast.spring.demo3.Bean3Factory"></bean> <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean> </syntaxhighlight> === 依赖注入(DI) === ---- DI(Dependency Injection):'''依赖注入''',使用IOC创建类的过程中,将类所依赖的属性设置进去。 ==== 依赖注入:方法 ==== ---- :[[File:依赖注入方法.png|800px]] # 构造函数注入: #: <syntaxhighlight lang="properties" highlight=""> <!-- 第一种:构造方法的方式--> <bean id="car" class="cn.itcast.spring.demo4.Car"> <constructor-arg name="name" value="保时捷"/> <constructor-arg name="price" value="1000000"/> </bean> </syntaxhighlight> # '''Setter注入''': #: <syntaxhighlight lang="properties" highlight=""> <!-- 第二种:set 方法的方式--> <bean id="car2" class="cn.itcast.spring.demo4.Car2"> <property name="name" value="奇瑞QQ"/> <property name="price" value="40000"/> </bean> </syntaxhighlight> # <s>接口注入:(要求组件必须与特定的接口相关联,不常使用)</s> ==== 依赖注入:应用 ==== ---- 常见的几个应用形式: * 【同样依靠与基本的“setter注入”(即必须有对应的set方法),只是写法或注入的内容不一样;】 # '''对象类型的注入''': #: <syntaxhighlight lang="properties" highlight="5"> <!-- 注入对象类型的属性--> <bean id="person" class="cn.itcast.spring.demo4.Person"> <property name="name" value="会希"/> <!-- ref 属性:引用另一个bean 的id 或name --> <property name="car2" ref="car2"/> </bean> </syntaxhighlight> # 名称空间p 的属性注入;(Spring2.x 以上) #: <syntaxhighlight lang="properties" highlight="3,14,15"> <!-- 第一步:引入p 名称空间 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 第二步:使用p 名称空间. * 普通属性: p:属性名称=”” * 对象类型属性: p:属性名称-ref=”” --> <!-- p 名称空间的属性注入的方式--> <bean id="car2" class="cn.itcast.spring.demo4.Car2" p:name=" 宝马7" p:price="1200000"/> <bean id="person" class="cn.itcast.spring.demo4.Person" p:name=" 思聪" p:car2-ref="car2"/> ... </syntaxhighlight> # '''SpEL''' 方式的属性注入:(Spring3.x 以上) #* SpEL:Spring Expression Language,语法;“'''#{ SpEL }'''”; #: <syntaxhighlight lang="properties" highlight=""> <!-- SpEL 的注入的方式--> <bean id="car2" class="cn.itcast.spring.demo4.Car2"> <property name="name" value="#{'奔驰'}"/> <property name="price" value="#{800000}"/> </bean> <bean id="person" class="cn.itcast.spring.demo4.Person"> <property name="name" value="#{'冠希'}"/> <property name="car2" value="#{car2}"/> </bean> </syntaxhighlight> #: <syntaxhighlight lang="properties" highlight=""> <!-- SpEL 引用另一个类的属性--> <bean id="carInfo" class="cn.itcast.spring.demo4.CarInfo"></bean> <bean id="car2" class="cn.itcast.spring.demo4.Car2"> <!-- <property name="name" value="#{'奔驰'}"/> --> <property name="name" value="#{carInfo.carName}"/> <property name="price" value="#{carInfo.calculatePrice()}"/> </bean> </syntaxhighlight> # 注入复杂类型: #: <syntaxhighlight lang="properties"> <!-- Spring 的复杂类型的注入 --> <bean id="collectionBean" class="cn.itcast.spring.demo5.CollectionBean"> <!-- 数组类型的属性--> <property name="arrs"> <list> <value>会希</value> <value>冠希</value> <value>天一</value> </list> </property> <!-- 注入List 集合的数据--> <property name="list"> <list> <value>芙蓉</value> <value>如花</value> <value>凤姐</value> </list> </property> <!-- 注入Map 集合--> <property name="map"> <map> <entry key="aaa" value="111"/> <entry key="bbb" value="222"/> <entry key="ccc" value="333"/> </map> </property> <!-- Properties 的注入--> <property name="properties"> <props> <prop key="username">root</prop> <prop key="password">123</prop> </props> </property> </bean> </syntaxhighlight> == Bean的管理:注解 == === 注解的相关配置 === “applicationContext.xml”中添加注解扫描: # 扫描“类”、“方法”、“属性”上面的注解: #*(包含了“<context:annotation-config>”的功能) #: <syntaxhighlight lang="properties"> <!-- Spring 的注解开发:组件扫描(类上注解: 可以直接使用属性注入的注解) --> <context:component-scan base-package="com.itheima.spring.demo1"/> </syntaxhighlight> # 扫描“属性”上面的注解: #: <syntaxhighlight lang="properties"> <!-- 扫描属性上面的注解 --> <context:annotation-config></context:annotation-config> </syntaxhighlight> === Bean相关的注解 === {| class="wikitable" ! 注解 !! 说明 |- ! colspan="2"| 对象注解 (Component及其衍生注解,功能一致) |- | '''@Component''' || 组件; |- | '''@Controller''' || WEB 层; |- | '''@Service''' || 业务层; |- | '''@Repository''' || 持久层; |- ! colspan="2"| 注入注解 (使用注解注入的方式,可以不用提供“set”方法) |- | '''@Value''' | 用于注入普通类型; |- | '''@Autowired''' | 自动装配; * 默认按类型进行装配;强制使用名称装配:“'''@Qualifier'''”; * “@Autowired(required=true)”:(默认)必须有一个Bean候选者注入; *: 如果允许出现0个Bean候选者需要设置属性:“required=false”; *:(required属性与“@Required”一样,只是@Required只适用于基于XML配置的setter注入方式) |- | '''@Resource''' | 相当于“@Autowired”和“@Qualifier” 一起使用; |- ! colspan="2"| 范围注解 |- | '''@Scope''' | 作用范围; # “singleton”:单例; # “prototype”:多例; |- ! colspan="2"| 生命周期 |- | '''@PostConstruct''' | 相当于“init-method”; |- | '''@PreDestroy''' | 相当于“destroy-method” |} 示例: <syntaxhighlight lang="java"> @Service(value="userService") public class UserService { // @Autowired // private UserDao userDao; // name属性值 写 注解创建dao对象 value值 @Resource(name="userDao") private UserDao userDao; // 使用注解方式时候不需要set方法 public void add() { System.out.println("service..........."); userDao.add(); } } </syntaxhighlight> == XML 与 注解 == [[File:XML与注解.jpg|400px]] * XML:结构清晰; * 注解:开发方便;(属性注入) ==== 混合使用 ==== # 创建对象操作使用配置文件方式实现: #: <syntaxhighlight lang="properties"> <!-- 开启注解扫描 --> <context:component-scan base-package="cn.itcast"></context:component-scan> <!-- 配置对象 --> <bean id="bookService" class="cn.itcast.xmlanno.BookService"></bean> <bean id="bookDao" class="cn.itcast.xmlanno.BookDao"></bean> <bean id="ordersDao" class="cn.itcast.xmlanno.OrdersDao"></bean> </syntaxhighlight> # 注入属性的操作使用注解方式实现: #: <syntaxhighlight lang="java"> public class BookService { //得到bookdao和ordersdao对象 @Resource(name="bookDao") private BookDao bookDao; @Resource(name="ordersDao") private OrdersDao ordersDao; public void add() { System.out.println("service........."); bookDao.book(); ordersDao.buy(); } } </syntaxhighlight> == 常见问题 == === 依赖对象冲突(@Qualifier、@Primary)=== 依赖对象冲突:即,具有多个符合条件的依赖对象;<br/> 为了解决这个问题,必须明确地指示 Spring 使用冲突的 bean 中的哪一个: ==== “@Qualifier” ==== @Qualifier 注解与“@Autowired”配合使用,来'''指定注入对象''': # 具有多个符合条件的依赖对象: #: <syntaxhighlight lang="java"> @Component("combustionEngine") public class CombustionEngine implements Engine { ... } </syntaxhighlight> #: <syntaxhighlight lang="java"> @Component("electricEngine") public class ElectricEngine implements Engine { ... } </syntaxhighlight> # 指定对象: #: <syntaxhighlight lang="java" highlight="5"> @Component public class Car { @Autowired public Car(@Qualifier("combustionEngine") Engine engine) { this.engine = engine; } ... } </syntaxhighlight> ==== “@Primary” ==== 将“@Primary”注释添加到类中,设置'''默认注入对象''': # 具有多个符合条件的依赖对象,但设置了“@Primary”类型: #: <syntaxhighlight lang="java" highlight="2"> @Component @Primary public class CombustionEngine implements Engine { ... } </syntaxhighlight> #: <syntaxhighlight lang="java"> @Component public class ElectricEngine implements Engine { ... } </syntaxhighlight> # 自动装配默认对象: #: <syntaxhighlight lang="java"> @Component public class Car { @Autowired public Car(Engine engine) { this.engine = engine; } ... } </syntaxhighlight> === 循环依赖(@Lazy)=== 如果对象之间出现了循环依赖,不能成功地创建其中任何一个Bean: <syntaxhighlight lang="java"> @Component public class Foo { private Bar bar; @Autowired public Foo(Bar bar) { this.bar = bar; } } </syntaxhighlight> <syntaxhighlight lang="java"> @Component public class Bar { private Foo foo; @Autowired public Bar(Foo foo) { this.foo = foo; } } </syntaxhighlight> Foo构造需要Bar对象,Bar构造需要Foo对象; 为了解决打破循环,可以使用“'''@Lazy'''”注释,允许其中一个Bean先初始化: * “@Lazy”使 Spring 推迟“带注解的bean”和“带注释的@Autowired位置”的初始化。 <syntaxhighlight lang="java" highlight="7"> @Component public class Foo { private Bar bar; @Autowired public Foo(@Lazy Bar bar) { this.bar = bar; } } </syntaxhighlight> <syntaxhighlight lang="java" highlight="2"> @Component @Lazy public class Bar { private Foo foo; @Autowired public Bar(Foo foo) { this.foo = foo; } } </syntaxhighlight>
返回至“
Spring:IOC
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息