依赖注入(dependency injection)
之前提到控制反转(Inversion of Control)也叫依赖注入,它们其实是一个东西,只是看的角度不同,这章详细说一下依赖注入。
依赖——指bean对象创建依赖于容器,bean对象依赖于资源(对象,常量,变量等)。
注入——bean对象依赖的资源通过容器来设置和装配(装配是指,比如一个对象A,需要一个对象B的实例,spring在配置对象A的时候,需要传入对象B的一个实例。会检查有没有有B,有的话,就拿来用,或者在配置对象其他属性时,传值的一个过程,叫装配)。
本章主要补充之前没有用到的注入方式,和总结学过的注入。
spring注入
常见的注入有下面这几种。p空间注入(spring2开始支持的注入,为了减少太多property引起的尖括号,需要在头文件中添加xmlns:p="http://www.springframework.org/schema/p", 如果报错点击File——Settings——Schemas and DTD,点加号,添加进去)
c空间注入(也是构造函数注入,和p空间注入用法一样,就没有写例子了),构造器注入,常量注入,数组注入,list注入,map注入,set注入,null注入,properties注入,bean注入。为了理解,以游戏为例,我们创建一个英雄。然后每种注入都用一次来配置。代码如下
目录
Hero代码
package cn.dota2.hero;
import cn.dota2.tpye.Type;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Hero {
public void setLv(String lv) {
this.lv = lv;
}
public void setExp(String exp) {
this.exp = exp;
}
private String name;//英雄姓名,通过构造器注入
private int hp,mp;//生命值,魔法值,通过常量注入
private Type hero_type;//肉盾类型。通过bean注入
private String[] article;//英雄持有物品,通过数组注入
private List<String> skill;//技能,通过list注入
private Map<String,String> buff;//英雄状态,String为名字,int为持续时间,通过map注入
private Set<String> group;//队友,通过set注入
private String gold;//金钱,NULL注入
private Properties cool_down;//技能cd。通过Properties注入
private String lv,exp;//等级,经验值。通过p空间注入
/**
* 构造器注入
* @param name 英雄姓名
*/
public Hero(String name){
this.name=name;
}
/**set方法**/
public void setHp(int hp) {
this.hp = hp;
}
public void setMp(int mp) {
this.mp = mp;
}
public void setHero_type(Type hero_type) {
this.hero_type = hero_type;
}
public void setArticle(String[] article) {
this.article = article;
}
public void setSkill(List<String> skill) {
this.skill = skill;
}
public void setBuff(Map<String, String> buff) {
this.buff = buff;
}
public void setGroup(Set<String> group) {
this.group = group;
}
public void setGold(String gold) {
this.gold = gold;
}
public void setCool_down(Properties cool_down) {
this.cool_down = cool_down;
}
/**set方法结束**/
public void show(){
System.out.println("英雄名:"+name);
System.out.println("生命值:"+hp+" 魔法值:"+mp);
System.out.println("英雄类型:"+ hero_type.getType());
System.out.println("英雄技能:"+skill);
System.out.println("技能状态:"+cool_down);
System.out.print("物品栏装备:");
for (int i=0;i<article.length;i++){
System.out.print(article[i]+" ");
}
System.out.println();
System.out.println("buff栏:"+buff);
System.out.println("队友:"+group);
System.out.println("当前金钱:"+gold);
System.out.println("当前经验值:"+exp+" 当前等级:"+lv);
}
}
Type代码
package cn.dota2.tpye;
public class Type {
private String type;//英雄类型
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Test代码
package cn.dota2.test;
import cn.dota2.hero.Hero;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
Hero doom=(Hero) ac.getBean("doom");
doom.show();
}
}
beans代码
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--通过p空间注入等级,经验值-->
<bean id="doom" class="cn.dota2.hero.Hero" p:lv="18" p:exp="12354">
<!--通过构造器注入传入英雄名字-->
<constructor-arg index="0" value="末日使者"/>
<!--通过常量注入传入英雄生命值,魔法值-->
<property name="hp" value="1000"/>
<property name="mp" value="500"/>
<property name="hero_type" ref="type"/>
<!--通过数组注入英雄装备-->
<property name="article">
<array>
<value>点金</value>
<value>飞鞋</value>
<value>辉耀</value>
</array>
</property>
<!--通过list注入英雄技能-->
<property name="skill" >
<list>
<value>吞噬</value>
<value>焦土</value>
<value>阎刃</value>
<value>末日</value>
</list>
</property>
<!--通过map注入英雄技能-->
<property name="buff">
<map>
<entry key="加速" value="10s"></entry>
<entry key="眩晕" value="5s"></entry>
</map>
</property>
<!--通过set注入英雄技能-->
<property name="group">
<set>
<value>蓝胖</value>
<value>刚背</value>
<value>猛犸</value>
<value>人马</value>
</set>
</property>
<!--null注入-->
<property name="gold"><null></null></property>
<!--通过properties注入技能状态-->
<property name="cool_down">
<props>
<prop key="末日">未学习</prop>
<prop key="吞噬">5s</prop>
<prop key="焦土">就绪</prop>
<prop key="阎刃">就绪</prop>
</props>
</property>
</bean>
<!--通过bean注入传入英雄类型-->
<bean id="type" class="cn.dota2.tpye.Type">
<property name="type" value="力量型英雄"/>
</bean>
</beans>
结果
这个例子也说明了spring的重要,如果不用依赖注入,那么游戏设计师每次设计技能,更新游戏数据,都需要更改源代码,这是非常危险的,而且游戏设计师不一定会,但是现在,我们只需要暴露出一个beans文件就可以了。