Spring IOC/DI 开发实践

Spring概述

对于java猿类来说,Spring使得java编程变得快捷,简单,安全。Spring聚焦于效率,简约,这使得Spring成为java世界最流行的框架没有之一。


IOC

IOC是Inverse of Control的缩写,意为控制反转,控制反转给谁,当然是Spring。IOC是面向对象的一种设计原则,用于降低代码的耦合度。DI(Dependency Injection)依赖注入是IOC最常见的一种实现方式。说的直白一点就是在一个APP里面对象的创建(使用Bean来创建)交给Spring,在创建对象时,依赖使用DI,例如A对象依赖B对象,Sping会把B的引用传给A,这种依赖关系可以在配置文件xml中配置,或使用注解注入。这就使得业务发生变化,若依赖发生变化只需要改配置,不需要改动代码。


IOC/DI XML配置(逐渐被注解替代)

只支持bean定义的schema

<?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
				        http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean id="userService" class="com.yp.demo.UserServiceImpl"/>
</beans>
bean标签
  • 1. id属性和name属性的区别
    • id 给Bean起个名字,在约束中采用ID的约束,唯一
    • id取值要求:必须以字母开始,可以使用字母、数字、连字符、下划线、句号、冒号,id不能出现特殊字符
    • name 给Bean起个名字,没有采用ID的约束(很少用
    • name取值要求:name可以出现特殊字符.如果bean没有id的话 , name可以当做id使用
  • 2. class属性
    • bean 类的全路径
  • 3. scope属性
    • singleton --单例:一般类的成员变量不对外暴露,即private,或者是只读的,能达到线程安全,那么这个bean就可以设置为singleton(单例),其实项目中的大多数bean都是单例管理的,可以节约内存,减轻GC负担
    • prototype --多例:一个典型的例子就是Struts2的Action类
    • request --应用在Web项目中,每次HTTP请求都会创建一个新的Bean
    • session --应用在Web项目中,同一个HTTP Session 共享一个Bean
    • globalsession --应用在Web项目中,多服务器间的session
  • 4. 生命周期方法
    • init-method --当bean被载入到容器的时候调用init-method属性指定的方法
    • destroy-method --当bean从容器中删除的时候调用destroy-method属性指定的方法
属性注入
  • 1. 构造器注入

编写类Car,添加一个带有属性的构造器,通过构造器注入属性

public class Car {
	private String name;
	
	private double money;
	
	private Person person;

	public Car(String name, double money) {
		super();
		this.name = name;
		this.money = money;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getMoney() {
		return money;
	}

	public void setMoney(double money) {
		this.money = money;
	}

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}
	
}

编写Car bean配置,使用constructor-arg注入

	<bean id="car" class="com.yp.demo.Car">
		<constructor-arg name="name" value="保时捷"/>
		<constructor-arg name="money" value="1000000"/>
	</bean>
  • 2. setter方法注入
    编写一个Person类,添加一个name属性的setter方法
public class Person {
	private String name;
	
	public Person() {
		
	}

	public Person(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
}

编写Person bean的配置,使用property注入

	<bean id="person" class="com.yp.demo.Person">
		<property name="name" value="隔壁老王"/>
	</bean>
  • 3. 一个Bean注入另一个Bean(最常用)
    这里演示Car中注入Person,在Car中添加如下代码,如1所示
	private Person person;
	
	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

在car 的bean配置中添加一个property,注意对象引用使用ref

	<bean id="car" class="com.yp.demo.Car">
		<constructor-arg name="name" value="保时捷"/>
		<constructor-arg name="money" value="1000000"/>
		<!-- bean中注入另一个bean -->
		<property name="person" ref="person"/>
	</bean>
  • 4. 测试代码
    从ApplicationContext 获取bean
	@Test
	public void test() {
		ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
			
		Car car = (Car) appContext.getBean("car");
		System.out.println(car.getName() + ":" + car.getMoney() + "---" + car.getPerson().getName());
		
		Person person = (Person) appContext.getBean("person");
		System.out.println(person.getName());
	}

运行结果

保时捷:1000000.0---隔壁老王
隔壁老王
  • 5. Spring的2.5版本中提供了一种:p名称空间的注入(很少用)
  • 步骤一:需要先引入 p 名称空间
    在schema的名称空间中加入该行
    xmlns:p=“http://www.springframework.org/schema/p”
<?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.xsd">
	
</beans>
  • 步骤二:使用p名称空间的语法
    p:属性名 = “”
    p:属性名-ref = “”
<?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.xsd">
	<bean id="person" class="com.yp.demo.Person" p:name="隔壁老张"/>
	<bean id="car" class="com.yp.demo.Car" p:name="法拉利" p:money="5000000" p:person-ref="person"/>
</beans>
  • 步骤三:示例
	@Test
	public void test1() {
		ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext2.xml");

		Car car = (Car) appContext.getBean("car");
		System.out.println(car.getName() + ":" + car.getMoney() + "---" + car.getPerson().getName());
		
		Person person = (Person) appContext.getBean("person");
		System.out.println(person.getName());
	}

运行结果:

法拉利:5000000.0---隔壁老张
隔壁老张
  • 6. Spring的3.0提供了一种:SpEL注入方式(不常用)
  • SpEL:Spring Expression Language是Spring的表达式语言,有一些自己的语法
  • 语法: #{SpEL}
  • 使用方式如下:
    bean配置如下
<?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.xsd">
	<bean id="person" class="com.yp.demo.Person" p:name="凤姐"/>
	<bean id="carInfo" class="com.yp.demo.CarInfo"/>
	<bean id="car" class="com.yp.demo.Car">
		<property name="name" value="#{carInfo.carName}"></property>
		<property name="money" value="#{carInfo.price}"></property>
		<property name="person" ref="person"></property>
	</bean>
</beans>

CarInfo类定义如下,SpEL支持从调用另一个bean的方法获取属性,

public class CarInfo {
	public String getCarName() {
		return "长安奔奔";
	}
	public double getPrice() {
		return 30000;
	}
}

测试代码及运行结果

	@Test
	public void test2() {
		ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext3.xml");

		Car car = (Car) appContext.getBean("car");
		System.out.println(car.getName() + ":" + car.getMoney() + "---" + car.getPerson().getName());
		
		Person person = (Person) appContext.getBean("person");
		System.out.println(person.getName());
	}
长安奔奔:30000.0---凤姐
凤姐
  • 7 集合注入(几乎不用)
    • List集合注入
    • Set集合注入
    • Map集合注入
    • Properties属性注入
  • 示例代码
public class User {	
	private List<String> list;
	public void setList(List<String> list) {
		this.list = list;
	}
	
	private Set<String> set;
	public void setSet(Set<String> set) {
		this.set = set;
	}
	
	private Map<String, String> map;
	public void setMap(Map<String, String> map) {
		this.map = map;
	}
	
	private Properties pro;
	public void setPro(Properties pro) {
		this.pro = pro;
	}
	
	@Override
	public String toString() {
		return "User [list=" + list + ", set=" + set + ", map=" + map + ", pro=" + pro + "]";
	}
}
  • 示例配置
	<bean id="user" class="com.yp.demo.User">
		<!--数组或者List集合,注入配置文件的方式是一样的-->
		<property name="list">
			<list>
				<value>小王</value>
				<value>小张</value>
			</list>
		</property>
		
		<!--Set集合注入的配置文件方式如下-->
		<property name="set">
			<set>
				<value>哈哈</value>
				<value>呵呵</value>
			</set>
		</property>
		
	    <!--Map集合,注入的配置方式如下-->
		<property name="map">
			<map>
				<entry key="隔壁老王" value="38"/>
				<entry key="楼上老王" value="38"/>
				<entry key="楼下老王" value="29"/>
			</map>
		</property>
	
		<!--Properties属性文件的方式-->
		<property name="pro">
			<props>
				<prop key="uname">root</prop>
				<prop key="pass">123</prop>
			</props>
		</property>
	</bean>
  • 测试运行
User [list=[小王, 小张], set=[哈哈, 呵呵], map={隔壁老王=38, 楼上老王=38, 楼下老王=29}, pro={uname=root, pass=123}]

IOC/DI 注解配置

Spring框架中Bean管理的常用注解

1. @Component:
    * 组件 作用在类上,相当于xml中的bean

3. Spring中提供@Component的三个衍生注解:
	* @Controller		-- 作用在WEB层
	* @Service			-- 作用在业务层
	* @Repository		-- 作用在持久层
	说明:这三个注解是为了让标注类本身的用途更清晰

4. 属性注入的注解(使用注解注入的方式,可以不用提供setter方法)
	* 如果是注入的普通类型,可以使用value注解
		* @Value			-- 用于注入普通类型,例如String、Integer等
	
	* 如果注入的是对象类型,使用如下注解
		* @Autowired		-- 默认按类型进行自动装配
			* 如果想按名称注入,加上@Qualifier
			* @Qualifier	-- 强制使用名称注入
	
	* @Resource				-- 相当于@Autowired和@Qualifier一起使用
		* 强调:JDK提供的注解
		* 使用name属性指明

Bean的作用范围和生命周期的注解

1. Bean的作用范围注解
	* 注解为@Scope(value="prototype"),作用在类上。值如下:
		* singleton		-- 单例,默认值
		* prototype		-- 多例

2. Bean的生命周期的配置
	* 注解如下:
		* @PostConstruct	-- 相当于init-method
		* @PreDestroy		-- 相当于destroy-method

注解IOC示例

1.引入context的约束,注册组件扫描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">	
	<!-- 这样默认扫描com.yp包下的所有注解 -->
	<context:component-scan base-package="com.yp"/>
</beans>
2. 代码示例
* service层
// @Component(value="userService")可以替代@Controller、@Service、@Repository
@Scope(value="singleton") // prototype多例模式
@Service(value="userService")// 作用在业务层,value是bean的名称
public class UserServiceImpl implements UserService {
	@Value(value = "花花")
	private String name;
	
	//@Autowired // 默认按类型自动装配
	//@Qualifier(value="userDao") // 按名称注入
	@Resource(name="userDao") // 作用相当于@Autowired和@Qualifier一起使用
	private UserDao userdao;

	@Override
	public void save() {
		System.out.println("保存用户...");
	}
	
	public void sayHello() {
		System.out.println("hello " + name + "!");
		userdao.saveUser();
	}
}

@Scope(value="singleton") // 单例模式
@Repository(value="userDao") // 作用在持久层
public class UserDaoImpl implements UserDao {
	@Override
	public void saveUser() {
		System.out.println("向数据库保存用户...");
	}
}

Spring框架整合JUnit单元测试

1. 为了简化了JUnit的测试,使用Spring框架也可以整合测试
2. 具体步骤
	* 要求:必须先有JUnit的环境(即已经导入了JUnit4的开发环境)!!
	
	* 步骤一:在程序中引入:spring-test.jar
	* 步骤二:在具体的测试类上添加注解
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value={"classpath:applicationContext.xml"})
public class Demo2 {
//  Spring直接注入UserService的对象,无需再写获取bean的setter语句
//	@Autowired
//	@Qualifier("userService")
	@Resource(name="userService")
	private UserService userService;
	
	@Test
	public void demo() {
		userService.sayHello();
	}
}
3. 运行结果
hello 花花!
向数据库保存用户...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值