1.spring学习小结-IOC与DI

基础部分IOC与DI

  Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,使用Spring开发可以将Bean对象,Dao组件对象,Service组件对象等交给Spring容器来管理,这样使得很多复杂的代码在Spring中开发却变得非常的优雅和简洁,有效的降低代码的耦合度,极大的方便项目的后期维护、升级和扩展。
在这里插入图片描述

简介:Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
 1.轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
 2.控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
 3.面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
 4.容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
 5.框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。

1. IOC( Inversion of Control),
  它把对象得创建交给了spring容器来完成,从而实现了松耦合。
下面是一位大佬得理解:
  IOC是Inversion of Control的缩写,多数书籍翻译成“控制反转”,还有些书籍翻译成为“控制反向”或者“控制倒置”。
1996年,Michael Mattson在一篇有关探讨面向对象框架的文章中,首先提出了IOC 这个概念。对于面向对象设计及编程的基本思想,前面我们已经讲了很多了,不再赘述,简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而降低了解决问题的复杂度,而且可以灵活地被重用和扩展。IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依 赖关系的对象之间的解耦,如下图:
在这里插入图片描述

  大家看到了吧,由于引进了中间位置的“第三方”,也就是IOC容器,使得A、B、C、D这4个对象没有了耦合关系,齿轮之间的传动全部依靠“第三方”了, 全部对象的控制权全部上缴给“第三方”IOC容器,所以,IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合 在一起发挥作用,如果没有这个“粘合剂”,对象与对象之间会彼此失去联系,这就是有人把IOC容器比喻成“粘合剂”的由来。
  我们再来做个试验:把上图中间的IOC容器拿掉,然后再来看看这套系统:
在这里插入图片描述

  我们现在看到的画面,就是我们要实现整个系统所需要完成的全部内容。这时候,A、B、C、D这4个对象之间已经没有了耦合关系,彼此毫无联系,这样的话, 当你在实现A的时候,根本无须再去考虑B、C和D了,对象之间的依赖关系已经降低到了最低程度。所以,如果真能实现IOC容器,对于系统开发而言,这将是 一件多么美好的事情,参与开发的每一成员只要实现自己的类就可以了,跟别人没有任何关系!
  我们再来看看,控制反转(IOC)到底为什么要起这么个名字?我们来对比一下:
  软件系统在没有引入IOC容器之前,如图1所示,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。
  软件系统在引入IOC容器之后,这种情形就完全改变了,如图3所示,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。
  通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。
2. 自己对IOC和DI的理解
   所谓IOC,其实就是对象创建的“控制权”被反转,IOC和DI就是从两个角度去说明一件事情,通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。
  正常程序中,当我们需要一个对象时,我们会在当前类中 new Object(),由我们自身控制,而这样就会使得对象间的耦合度高了。当使用IOC后,我们只需要向IOC容器去要,而不关心该对象如何创建与何时创建,对象的创建由IOC控制,从而降低了程序之间的耦合。

spring操作步骤

一、非注解使用(不常用)
1.导入spring核心依赖jar包
在这里插入图片描述
2.创建spring核心配置文件applicationContext.xml文件

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://www.springframework.org/schema/beans" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">

	<!-- 一个bean就是一个类 -->
	<!-- 我把Girl类配置到了spring中  -->
	<bean name="girl1" class="com.zhx.pojo.Girl"></bean>
	
	
</beans>

3.创建并封装该实体类,
4.在demo中拿到该类

	@Test
	public void test2(){
		/*
		 * 先拿到spring框架的核心的类:ApplicationContext类。
		 * 拿到ApplicationContext类,相当于你拿到了spring框架。
		 * 问题:就是ApplicationContext类如何创建对象?有哪些方法?
		 */
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		/*
		 * 父类的引用,引用着子类的对象。多态! 
		 * 子类构造方法参数:配置文件的名字!
		 */
		// 向spring"要"Girl对象(spring去给我创建对象,我可以直接拿来就用)
		Girl g1 = (Girl) ac.getBean("girl1");
		// 打印测试
		System.out.println(g1);
		/*
		 * 注意:
		 * spring容器在创建对象的时候,默认采用的是类的无参构造!
		 * 所以,你就必须写无参构造!
		 */
	}
	

5.bean的装配方式与方法装配

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://www.springframework.org/schema/beans" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">

	<!-- 配置一个Girl类 -->
	<!-- <bean name="girl1" class="com.zhx.pojo.Girl" /> -->
	
	<!-- 配置一个Girl类,还配置了类中的两个方法,
	一个是对象创建之后的初始化方法,
	一个是对象销毁之前的回收方法。
	 -->
	<!-- <bean name="girl1" class="com.zhx.pojo.Girl" init-method="init" destroy-method="destroy"></bean> -->
	
	<!-- 配置一个Girl类(对象个数问题) -->
	<!-- spring框架:默认一个类只给创建一个对象!  -->
	<!-- <bean name="girl1" class="com.zhx.pojo.Girl" /> -->
	
	<!-- spring框架对象个数,默认单个:scope="singleton": singleton:单例  -->
	<!-- <bean name="girl1" class="com.zhx.pojo.Girl" scope="singleton"/> -->
	
	<!-- spring框架对象个数,多个:scope="prototype": prototype:原型,get几个,就创建几个对象  -->
	<!-- <bean name="girl1" class="com.zhx.pojo.Girl" scope="prototype"/> -->
	
	<!-- 静态工厂,创建对象 -->
	<!-- 把静态工厂类配置到spring  -->
	<!-- <bean name="girl2" class="com.zhx.test2.GirlFactory1" factory-method="newGirl" /> -->
	
	<!-- 实例工厂,创建对象 -->
	<!-- 把实例工厂类配置到spring  -->
	<bean name="gf" class="com.zhx.test2.GirlFactory2" />	
	<!-- 通过实例工厂,配置一个Girl的类 -->
	<bean name="girl3" factory-bean="gf" factory-method="newGirl"/>
	
</beans>
import com.zhx.pojo.Girl;

/**
 * 工厂类! (静态工厂)
 *	创建对象!
 */
public class GirlFactory1 {
	
	public static Girl newGirl(){
		return new Girl();
	}
}

import com.zhx.pojo.Girl;

/**
 * 工厂类! (动态(实例)工厂)
 *	创建对象!
 */
public class GirlFactory2 {
	
	public Girl newGirl(){
		return new Girl();
	}
}
	// 测试spring静态工厂创建对象
	@Test
	public void test3(){
		
		// 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext2.xml");
		
		// 要对象
		Girl g1 = (Girl)ac.getBean("girl2");
		// 打印对象
		System.out.println(g1);
	}
	
	// 测试spring动态工厂创建对象
	@Test
	public void test4(){
		
		// 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext2.xml");
		
		// 要对象
		Girl g1 = (Girl)ac.getBean("girl3");
		// 打印对象
		System.out.println(g1);
	}import com.zhx.pojo.Girl;

/**
 * 工厂类! (静态工厂)
 *	创建对象!
 */
public class GirlFactory1 {
	
	public static Girl newGirl(){
		return new Girl();
	}
}

import com.zhx.pojo.Girl;

/**
 * 工厂类! (动态(实例)工厂)
 *	创建对象!
 */
public class GirlFactory2 {
	
	public Girl newGirl(){
		return new Girl();
	}
}
	// 测试spring静态工厂创建对象
	@Test
	public void test3(){
		
		// 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext2.xml");
		
		// 要对象
		Girl g1 = (Girl)ac.getBean("girl2");
		// 打印对象
		System.out.println(g1);
	}
	
	// 测试spring动态工厂创建对象
	@Test
	public void test4(){
		
		// 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext2.xml");
		
		// 要对象
		Girl g1 = (Girl)ac.getBean("girl3");
		// 打印对象
		System.out.println(g1);
	}

6.属性的注入

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://www.springframework.org/schema/beans" 
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">

	<!-- set方式注入 -->
	<!-- 配置Girl类,并且赋值 -->
 	<bean name="girl1" class="com.zhx.pojo.Girl">
		<property name="name" value="zhang1"/>
		<property name="age" value="21"/>
	</bean> 
	
	<!-- 配置Dog类,并且赋值 -->
	<bean name="dog1" class="com.zhx.pojo.Dog">
		<property name="name" value="黑虎"/>
		<property name="color" value="黑色"/>
	</bean>
	
	<!-- 配置Boy类,并且赋值 -->
 	<bean name="boy1" class="com.zhx.pojo.Boy">
		<property name="name" value="wang1"/>
		<property name="age" value="90"/>
		<property name="dog" ref="dog1"/>
	</bean>
	<!--  
		spring容器在给对象属性赋值时,默认使用的是属性对应的set方法!
	 -->
	
	<!-- 构造方法注入  -->
	<!-- Girl类 -->
 	<bean name="girl2" class="com.zhx.pojo.Girl">
		<constructor-arg name="name" value="zhang2"></constructor-arg>
		<constructor-arg name="age" value="22"></constructor-arg>
	</bean> 
	
	<!-- Boy类 -->
 	<bean name="boy2" class="com.zhx.pojo.Boy">
		<constructor-arg name="name" value="wang2"></constructor-arg>
		<constructor-arg name="age" value="92"></constructor-arg>
		<constructor-arg name="dog" ref="dog1"></constructor-arg>
	</bean>
	
	<bean name="boy2" class="com.zhx.pojo.Boy">
		<constructor-arg name="name" value="wang2" index="1" type="java.lang.String"></constructor-arg>
		<constructor-arg name="age" value="92" index="0" type="java.lang.Integer"></constructor-arg>
		<constructor-arg name="dog" ref="dog1" index="2" type="com.wang.pojo.Dog"></constructor-arg>
	</bean> 
	
	<!-- p名称空间注入 -->
	<bean name="boy3" class="com.zhx.pojo.Boy" p:name="wang3" p:age="93" p:dog-ref="dog1"></bean>
	
	<!-- spel(sp=spring,el表达式) -->
	<bean name="boy4" class="com.zhx.pojo.Boy">
		<property name="name" value="#{boy3.name}"></property>
		<property name="age" value="#{boy3.age}"></property>
		<property name="dog" ref="dog1"></property>
	</bean>
	
</beans>
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.zhx.pojo.Boy;
import com.zhx.pojo.Dog;
import com.zhx.pojo.Girl;

public class Demo3 {

	// Gril类
	@Test
	public void test1() {
		// 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext3.xml");
		// 对象
		Girl g1 = (Girl) ac.getBean("girl1");
		// 打印
		System.out.println(g1);
	}
	
	// Dog类
	@Test
	public void test2() {
		// 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext3.xml");
		// 对象
		Dog d1 = (Dog) ac.getBean("dog1");
		// 打印
		System.out.println(d1);
	}
	
	// Boy类
	@Test
	public void test3() {
		// 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext3.xml");
		// 对象
		Boy b1 = (Boy) ac.getBean("boy1");
		// 打印
		System.out.println(b1);
	}
	
	// Girl类(构造注入)
	@Test
	public void test4() {
		// 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext3.xml");
		// 对象
		Girl g1 = (Girl) ac.getBean("girl2");
		// 打印
		System.out.println(g1);
	}
	
	// Boy类(构造注入)
	@Test
	public void test5() {
		// 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext3.xml");
		// 对象
		Boy b2 = (Boy) ac.getBean("boy2");
		// 打印
		System.out.println(b2);
	}
	
	// Boy类(p名字空间注入)
	@Test
	public void test6() {
		// 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext3.xml");
		// 对象
		Boy b3 = (Boy) ac.getBean("boy3");
		// 打印
		System.out.println(b3);
	}
	
	// Boy类(spel注入)
	@Test
	public void test7() {
		// 容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext3.xml");
		// 对象
		Boy b4 = (Boy) ac.getBean("boy4");
		// 打印
		System.out.println(b4);
	}

}

7.数组,对象和Map注入

/**
 * 实体类。
 *
 */
public class Entity {
	
	// 数组
	private Object[] arr;
	
	// list
	private List<Object> list;
	
	// map
	private Map<String, Object> map;
	
	// properties
	private Properties prop;
	
	@Override
	public String toString() {
		return "Entity [arr=" + Arrays.toString(arr) + ", list=" + list + ", map=" + map + ", prop=" + prop + "]";
	}

	public Object[] getArr() {
		return arr;
	}

	public void setArr(Object[] arr) {
		this.arr = arr;
	}

	public List<Object> getList() {
		return list;
	}

	public void setList(List<Object> list) {
		this.list = list;
	}

	public Map<String, Object> getMap() {
		return map;
	}

	public void setMap(Map<String, Object> map) {
		this.map = map;
	}

	public Properties getProp() {
		return prop;
	}

	public void setProp(Properties prop) {
		this.prop = prop;
	}

}
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans" 
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">

	<!-- <bean name="girl1" class="com.zhx.domain.Girl">
		<property name="name" value="wang1"></property>
		<property name="age" value="41"></property>
	</bean>
	-->
	
	<!-- 配置Entity类  -->
	<bean name="entity" class="com.zhx.pojo.Entity"></bean>
	
	
	<bean name="entity2" class="com.zhx.pojo.Entity">
	
		<!-- 给数组注入 -->
		<property name="arr">
			<array>
				<value>aaa</value>
				<value>bbb</value>
				<value>ccc</value>
				<!-- <ref bean="girl1" /> -->
			</array>
		</property>
		
		<!-- 给List注入 -->
		<property name="list">
			<list>
				<value>zhang1</value>
				<value>zhang2</value>
				<value>zhang3</value>
				<!-- <ref bean="girl1" /> -->
			</list>
		</property>
		
		<!-- 给Map注入 -->
		<property name="map">
			<map>
				<entry key="key1" value="lili1"></entry>
				<entry key="key2" value="lili2"></entry>
				<!-- <entry key="key3" value-ref="girl1"></entry> -->
			</map>
		</property>
		
		<!-- 给Properties注入 -->
		<property name="prop">
			<props>
				<prop key="driverClass">com.jdbc.mysql.Driver</prop>
				<prop key="url">jdbc:mysql://127.0.0.1:3308/db1</prop>
				<prop key="userName">root</prop>
				<prop key="password">123456</prop>
			</props>
		</property>
	</bean>
</beans>

二、注解方式(后期)

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://www.springframework.org/schema/beans" 
	xmlns:context="http://www.springframework.org/schema/context" 
	xsi:schemaLocation="
	http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-4.2.xsd 
	http://www.springframework.org/schema/context 
	http://www.springframework.org/schema/context/spring-context-4.2.xsd ">

	<!-- 配置一个包,让spring来扫描,spring其实是扫描类上(类中)的注解。 -->
	<context:component-scan base-package="com.zhx.pojo"></context:component-scan>
	
	
	
</beans>

spring基本注解

	 * IOC:	@Component,@Controller,@Service,@Repository.
	 * DI:@Value,@Resource,@Autowared
	 * 其他:@PostConstrut,@PreDestroy
	 */
@Component("girl1")	// 把类放容器
//@Controller("girl1")
//@Service("girl1")
//@Repository("girl1")

//@Scope(scopeName="singleton")
//@Scope(scopeName="prototype")
public class Girl {
	
	/*
	 * spring定义的4个注解(加在类上);
	 * @Componet	组件
	 * @Controller	控制层
	 * @Service		Service层
	 * @Repository	数据层
	 * 
	 * 作用:IOC
	 * 把这个类告诉spring,spring收到后,创建对象!
	 * 采用注解后,就不用再配置文件中去专门配置<bean>
	 */
	
	/*
	 * @Scope注解:控制对象的个数!
	 */
	
	/*
	 * @Value():给对象赋值。
	 */
	
	@Value("zhang1")
	private String name;
	@Value("21")
	private Integer age;
	
	public Girl() {
	}
	
	public Girl(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	@Override
	public String toString() {
		return "Girl [name=" + name + ", age=" + age + "]";
	}

	public String getName() {
		return name;
	}

//	@Value("zhang2")
	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}
}
/**
 * spring的单元测试!
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)	// spring的单元测试(spring + junit)
@ContextConfiguration("classpath:applicationContext.xml") //spring的配置文件
public class Demo1 {
	
//	@Resource(name="girl1")
//	private Girl g1;
	
//	@Resource(name="boy1")
//	private Boy b1;
	
	/**
	 * junit测试!
	 */
	@Test
	public void test0(){
		// 容器对象(把spring框架跑起来)
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		// 向容器"要"对象 
		Girl g1 = (Girl) ac.getBean("girl1");
		// 打印测试
		System.out.println(g1);
	}
	
	// 向容器去要一个Girl的对象
	@Autowired
	private Girl g1;
	
	@Test
	public void test1(){
		// 打印测试
		System.out.println(g1);
	}
	
	
	// 向容器要Boy
	@Autowired
	private Boy boy1;
	
	@Test
	public void test2(){
		// 打印测试
		System.out.println(boy1);
	}
	
	/*
	 * spring单元测试:
	 * jar包(spring-test-xxx.jar)
	 * 
	 * SpringJUnit4ClassRunner类:spring的单元测试类。
	 * @ContextConfiguration注解:spring的注解,设置spring的配置文件。
	 * @RunWith注解:junit的注解。和spring的单元测试整合!
	 * @Test:junit的注解,测试哪个方法!
	 */

}

特别提示:spring框架在后面整合时候会通过web.xml里面配置spring启动(如下图所示),从而不需去生成ApplicationContext对象来跑spring。

<!-- spring(启动) -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext-*.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值