spring 全局变量_[Spring]-Spring框架-02-IOC容器

Spring框架

IOC容器

理解IOC容器和DI依赖注入

IOC容器 Inverser Of Control反转控制 就是把原来在程序中创建HelloService对象的控制权限交给Spring管理,简单的说 就是HelloService对象控制器被反转到Spring框架内

3fc59e7794a3e7725e1db92a83cc0c6b.png

DI: 依赖注入 在Spring框架负责创建Bean对象的时候 动态的将数据注入到Bean的组件

cd7411300b6258d55ba7ea526ecc62e9.png

IOC容器装配Bean的方式(XML配置方式)

IOC容器装配Bean的方式就是实例化该对象的方式,Spring提供了三种装配Bean的方式

  • 使用类的构造函数进行初始化 (默认是无参的构造函数)
  • 使用静态工厂方法:利用factory-method=属性指定静态工厂方法
  • 使用实例化工厂方法 (工厂模式)
/**       
 * 通过3种方式获取Bean对象   
 *  a.根据获取Bean对象不同的方式定义相关内容
 *  	根据构造器获取
 *  	利用静态工厂方法获取
 *  	利用实例化工厂方法获取
 *  b.在applicationContext.xml中进行配置
 *  c.获取Bean对象进行测试
 *  	url : "spring/applicationContext.xml" 指定核心配置文件位置
 *  	ApplicationContext ac = new ClassPathXmlApplicationContext(url);
 *  	BeanClass bean = ac.getBean("id");
 */

a.构造函数初始化

<1>定义Bean实体,提供无参构造函数

Bean.java:

/**       
 * 方式1:利用构造器获取   
 */
public class Bean {
	// 定义一个无参的构造方法,系统有默认的无参构造器
}

<2>在核心配置文件applicationContext.xml中定义bean对象

<!-- 
	a.构造函数初始化 
		<bean id="" class=""></bean>
		id:实例对象名称
		class:对应类全名
-->
<bean id="bean" class="com.guigu.spring.b_instance.Bean"></bean>

<3>编写代码获取指定对象进行测试

/**
*  方式1:通过构造器获取Bean对象
*/
	@Test
	public void testGetBean1() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
        Bean bean =(Bean) applicationContext.getBean("bean");
        System.out.println("方式1:"+bean);
	}

<4>查看测试结果

e336807d97cc81ebee33f429003945a7.png

b.使用静态工厂方法

<1>定义Bean实体,工厂方法设计模式

ClientService.java:

/**
 * 方式2:利用静态工厂方法获取 此处类似于单例模式
 */
public class ClientService {
	// a.构造函数私有化
	private ClientService() {

	}

	// b.提供一个静态的私有的属于自己的全局变量进行初始化
	private static ClientService clientService = new ClientService();

	// c.通过提供公有方法返回该对象
	public static ClientService createInstance() {
		return clientService;
	}
}

<2>在核心配置文件applicationContext.xml中定义bean对象

<!-- 
  	 b.使用静态工厂方法 
  	 	<bean id="" class="" factory-method=""></bean>
  	 	id:实例对象名称
  	 	class:对应类全名
  	 	factory-method:返回该实例对象的工厂方法名
-->
<bean id="clientService" class="com.guigu.spring.b_instance.ClientService"  factory-method="createInstance"></bean>

<3>编写代码获取指定对象进行测试

575c89fa878774097a1e54ef274c5195.png

<4>查看测试结果

feedac8858215597b404f223b3846411.png

c.使用实例化工厂方法

<1>定义Bean实体,实例化工厂方法设计模式

UserService.java:

/**
 * 方式3:实例化工厂方法
 * a.先创建一个实体类xxx
 * b.通过xxxFactory进行实例化并返回某个对象
 */
public class UserService {

}
UserServiceFactory.java:
public class UserServiceFactory {
	// 创建UserService 是通过UserServiceFactory 完成实例化
	private static UserService userService = new UserService();
	// 提供共有方法返回实例化对象
	public UserService createUserServiceInstance() {
		return userService;
	}
}

<2>在核心配置文件applicationContext.xml中定义bean对象

<!-- 
  	 c.使用实例化工厂方法 
  	<bean id="xxxFactory" class="xxxFactory工厂类全名"></bean>
  	<bean id="实例对象名称" factory-bean="xxxFactory" factory-method="调用工厂方法名"></bean>
-->
  	<bean id="userServiceFactory" class="com.guigu.spring.b_instance.UserServiceFactory"></bean>
  	<bean id="userService" factory-bean="userServiceFactory" factory-method="createUserServiceInstance"></bean>

<3>编写代码获取指定对象进行测试

a2eecaa22c6bb3cee40911fff194fc8b.png

<4>查看测试结果

68c2cb8de396447ebdbc635fbb376c57.png

Bean的其他属性配置——作用域

定义Bean的时候可以指定以下方式

f2fd1dd762b3c97ba10f401d7599add7.png

7be72f547e8281da34219e10b778a688.png
  • singleton

9e57a43ab95177f38004b67372b02b3b.png
  • prototype

9d6356b4e36743ca2891d186b0fbe4a4.png

2502b511e46577ba4e614d85a7c69cc0.png

<1>定义实体类product

/**       
 * 定义Product类,提供无参构造方法   
 */
public class Product {
 public Product() {
		System.out.println("product实例化......");
	}
}

<2>核心配置文件进行Bean配置

<!-- a.单例模式配置:scope="singleton" -->

<bean id="product1" class="com.guigu.spring.c_scope.Product" scope="singleton"></bean>
<!-- b.多例模式配置:scope="prototype" -->
<bean id="product2" class="com.guigu.spring.c_scope.Product" scope="prototype"></bean>
<!-- c.还有其他作用域设置需根据实际项目需求进行选择,详细参考实际文档 -->

<3>编写测试文件进行测试

public class ProductTest {
	@Test
	public void testSingletonScope() {
		/**
		 * 单例模式测试结果显示:
		 * product被实例化1次,且均为执行同一个对象(指向对象地址相同)
		 */
		ApplicationContext ac =new ClassPathXmlApplicationContext("spring/applicationContext.xml");
        Product p1 = (Product) ac.getBean("product1");
        Product p2 = (Product) ac.getBean("product1");
        System.out.println(p1);
        System.out.println(p2);
	}
	
	@Test
	public void testPrototypeScope() {
		/**
		 * 多例模式测试结果显示:
		 * product被实例化多次,且均指向不同的对象(指向对象的地址不同)
		 */
		ApplicationContext ac =new ClassPathXmlApplicationContext("spring/applicationContext.xml");
        Product p1 = (Product) ac.getBean("product2");
        Product p2 = (Product) ac.getBean("product2");
        System.out.println(p1);
        System.out.println(p2);
	}
}

Singleton测试结果:

6abdb5a30733de64825a975125cbab8d.png

Prototype测试结果:

ccbf61dd645e745a2a136e5729ec8607.png

Bean属性依赖注入

b55866f77210be9a9bc4463d645ab108.png

Bean属性的注入分为构造器注入、setter方法注入

步骤:
1.定义实体对象
2.在核心配置文件中定义相关属性
3.编写测试文件进行测试

a.第一种构造器注入

539c854b0bcb766ff5f902833fca190c.png
实体类定义如下:
public class Car {
	// 定义Car类的两个属性
	private String carType ;
	private String carPrice;
	// 提供带参数的构造器
	public Car(String carType, String carPrice) {
		super();
		this.carType = carType;
		this.carPrice = carPrice;
	}
	@Override
	public String toString() {
		return "Car [carType=" + carType + ", carPrice=" + carPrice + "]";
	}
}

<1>使用构造函数的参数类型进行注入

在核心配置文件中定义相关属性:

bd6c22b58826852f5761735761b234bc.png

编写测试代码:

ea48695c55d0d5faa0696cbc769baff8.png

测试结果:

5bbeecde590da0bb7a1ee550000b53d7.png

<2>构造函数的参数的索引、下标

在核心配置文件中定义相关属性:

2b5de896c7096aa0764eb26d164911a3.png

编写测试代码:

7fcee9c96782397ab47c5df67f7c36f4.png

测试结果:

a37790301aa9d6fc73fb9afb1b671374.png

<3>构造函数参数的名称

在核心配置文件中定义相关属性:

bba9745726bf684522988ddd8d930c8b.png

编写测试代码:

93d1a24bd5587777893458d94301fe20.png

测试结果:

880815def1d470ec921c9bf6bf50b1fb.png

b.Setter方法注入

3c45bdeb1028da5bd1c1bbb7b38b98fb.png

<1>Setter方法注入简单数据

创建Cellphone实体:

public class Cellphone {
	// 定义Cellphone的两个属性
	private String phoneName;
	private String phonePrice;
	// 提供setter方法
	public void setPhoneName(String phoneName) {
		this.phoneName = phoneName;
	}
	public void setPhonePrice(String phonePrice) {
		this.phonePrice = phonePrice;
	}
	@Override
	public String toString() {
		return "Cellphone [phoneName=" + phoneName + ", phonePrice=" + phonePrice + "]";
	}
}

核心文件applicationContext.xml配置:

e6148e334850d222445973fd96b5c847.png

代码测试:

d440dd4954babbed5ff67f703ceb0e0a.png

测试结果:

2804ee0046edacdfe1e07c0a2a05c97b.png

<2>Setter方法注入复杂对象

在上述内容的基础上定义Person实体拥有Car、Cellphone属性:

public class Person {
	// 定义Person的3个属性
	private String name;
	private Car car;
	private Cellphone phone;
	// 提供setter方法
	public void setName(String name) {
		this.name = name;
	}
	public void setCar(Car car) {
		this.car = car;
	}
	public void setPhone(Cellphone phone) {
		this.phone = phone;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", car=" + car + ", phone=" + phone + "]";
	}
}

核心文件applicationContext.xml配置:

90af6031076756965fbb3b24107551df.png

代码测试:

7f5720fdea5b1363b5f2d06444328db3.png

测试结果:

a1724baa91ecb14fe7ada8c430590876.png

<3>集合属性的注入

9c1b8218549d58395cfa51482c0ecfa5.png

定义测试对象CollectionBean:

public class CollectionBean {
	// 定义CollectionBean的四个属性
	private List<String> list;
	private Set<Integer> set;
	private Map<String,String> map;
	private Properties properties;
	// 提供相应的setter方法
	public void setList(List<String> list) {
		this.list = list;
	}
	public void setSet(Set<Integer> set) {
		this.set = set;
	}
	public void setMap(Map<String, String> map) {
		this.map = map;
	}
	public void setProperties(Properties properties) {
		this.properties = properties;
	}
	@Override
	public String toString() {
		return "CollectionBean [list=" + list + ", set=" + set + ", map=" + map + ", properties=" + properties + "]";
	}
}

核心文件applicationContext.xml配置:

<bean id="collectionBean" class="com.guigu.spring.d_di.CollectionBean">
		<!-- 作为参考,此处注入的均为普通数据类型的集合元素,可以注入其他的bean元素 -->
		<!-- 
			a.list集合属性的注入 
			<property name="属性名称">
				<list>
					<value>注入值:普通数据</value>
				</list>
			</property>
		-->
		<property name="list">
			<list>
				<value>list项1</value>
				<value>list项2</value>
				<value>list项3</value>
			</list>
		</property>
		<!--  
			b.set集合属性的注入
			<property name="属性名称">
				<set>
					<value>注入值:普通数据</value>
				</set>
			</property>
		-->
		<property name="set">
			<set>
				<value>1</value>
				<value>2</value>
				<value>3</value>
			</set>
		</property>
 
		<!--  
			c.map集合属性的注入
			<property name="属性名称">
				<map>
					<entry key="key值" value="value值"></entry>
				</map>
			</property>
		-->
		<property name="map">
			<map>
				<entry key="username" value="hahabibu"></entry>
				<entry key="password" value="000000"></entry>
			</map>
		</property>
 
		<!--  
			d.properties集合属性的注入
			<property name="属性名称">
				<props>
					<prop key="key值">value值</prop>
				</props>
			</property>
		-->	
		<property name="properties">
			<props>
				<prop key="company">杭州归谷</prop>
				<prop key="address">浙江杭州</prop>
			</props>
		</property>
</bean>

代码测试:

4b185ade1496e59d518a58a2cfc8b825.png

测试结果:

02ec1e9045333a2838a47314e24646ef.png

09223416a4dc57e61f0b7e0c77edfc71.png

<4>P命名空间的使用

4f230722528ab606d7a3ba21bc985e60.png

核心配置文件中引入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">

a0874452455c2d8592a65c1c994fefdd.png

创建实体类Computer:

public class Computer {
	// 提供Computer的两个属性
	private String cname;
	private String cprice;
	// 提供setter方法
	public void setCname(String cname) {
		this.cname = cname;
	}
	public void setCprice(String cprice) {
		this.cprice = cprice;
	}
	@Override
	public String toString() {
		return "Computer [cname=" + cname + ", cprice=" + cprice + "]";
	}
}

核心配置文件中进行配置:

4fcb4ff52ac776d5934e8f5918694078.png

编写测试代码:

cd3533b8af20b66ae3901a39a3e710d2.png

测试结果:

371108d5b5cd0fc902a9ae33ffea7608.png

48aa5979fd65e0cc615420c3531c9a86.png

多个xml配置文件

f7a9d6d8a717d97d09a4d783a07ec3b4.png

方式一 :在类中执行的时候添加多个文件(不推荐使用)

appliicationContext.xml定义如上述所示,appliicationContext2.xml定义如下

c6161bf9c28563a87d7451f45d731311.png
@Test
	public void testXML1() {
		ApplicationContext ac =new ClassPathXmlApplicationContext("spring/applicationContext.xml","spring/applicationContext2.xml");
		Person p1 = (Person) ac.getBean("p1");
		System.out.println(p1);
	}

方式二 :在一个总的文件中引入不同的配置文件,然后在代码中使用这个总的配置文件

applicationContext_all.xml:

a281a5fa8e1e6edac263161689b954e8.png
// 调用总的文件以引入不同的配置文件
	@Test
	public void testXML2() {
		ApplicationContext ac =new ClassPathXmlApplicationContext("spring/applicationContext_all.xml");
		Person p2 = (Person) ac.getBean("p2");
		System.out.println(p2);
	}

IOC容器装配Bean(注解的方式)

a.使用注解定义Bean

<1>定义配置文件

引入context命名空间

配置Spring的自动扫描和要扫描的包

b003a21b8b54a1abdaee02f9eb6794f1.png

applicationContext.xml:

<!-- 配置注解bean自动扫描 -->
 	<context:annotation-config/>
 	<!-- 定义具体扫描的包 -->
 	<context:component-scan base-package="com.guigu.spring.a_beandefinition,com.guigu.spring.b_scope">
</context:component-scan>

<2>需要在Bean对象中定义@Component 声明组件

f2926fa5b456b9e70ecc6a85a8d1d01e.png

<3>测试代码

c59eb7b18d88edf6fa83d1f79a557b89.png

<4>测试结果

ede4cbb520de6e9da0e0eb16c9043f0a.png

除了@Component外,Spring提供了3个功能基本和@Component等效的注解

  • @Repository 用于对DAO实现类进行标注
  • @Service 用于对Service实现类进行标注
  • @Controller 用于对Controller实现类进行标注

这三个注解是为了让标注类本身的用途清晰,Spring已对其增强

@Repository测试

ceedf7c556ddf36d43ea0e4d39b71a44.png

2887efc5db5f910585945af61ed08672.png

测试结果:

18bb9f46948f2f8492d34d997e90c82a.png

@Service测试

d9ff4a02eacffc0b15bdea685716a31a.png

87c28018791e6986fd636ea1992a8960.png

测试结果:

ca7a647d7eaf548371a3faf7a9642ee8.png

@Controller测试

bfeb55f34c5b794f57f4c9289ba2e62d.png

02fb6afd46ef6e61e6f985d1b3783bd7.png

测试结果:

4b6016c8a9959eb964df19c533b86e06.png

@Autowired默认是根据类型自动注入

  • 通过@Autowired的required属性,设置一定要找到匹配的Bean
  • 使用@Qualifier指定注入Bean的名称
  • 使用Qualifier 指定Bean名称后,注解Bean必须指定相同名称

@Autowired(required=false)默认是true 如果注入不成功就会报错 False 空指针

如果存在多个相同的类型注入就会报错,可以再使用类型的前提下再次明确使用哪个Bean对象就是使用

@Qualifier("userService") 明确指定使用哪个Bean对象

使用@Resource可以优化上方两个注解:

@Resource(name="userService")

等价于

@Autowired(required=false)

@Qualifier("userService")

bf32ddb158cb21dd9758b0a2a2300871.png

b.Bean的范围

<1>在applicationContext.xml中声明要进行扫描的包

<2>定义Car类进行作用范围测试

96203e9756027aa221c627684e723442.png

<3>编写测试文件

89424862a05439abb9b54787f10a4839.png

<4>测试结果分析

如果指定作用范围为prototype多例模式显示如下内容

00f23b23fb47a600afec281ef159ee7d.png

如果指定作用范围为singleton单例模式则显示如下内容

0fd94d514e993b3517991968dc1d909d.png

c.注册Bean的注解

Spring3.0以JavaConfig为核心,提供使用Java类定义Bean信息的方法

  • @Configuration 指定POJO类为Spring提供Bean定义信息
  • @Bean 提供一个Bean定义信息

<1>定义model对象Cellphone、Product

Cellphone.java:
public class Cellphone {
	private String cname;
	private String cprice;
	public String getCname() {
		return cname;
	}
	public void setCname(String cname) {
		this.cname = cname;
	}
	public String getCprice() {
		return cprice;
	}
	public void setCprice(String cprice) {
		this.cprice = cprice;
	}
	@Override
	public String toString() {
		return "Cellphone [cname=" + cname + ", cprice=" + cprice + "]";
	}
}
Product.java:
public class Product {
	private String pname;
	private String pprice;
	public String getPname() {
		return pname;
	}
	public void setPname(String pname) {
		this.pname = pname;
	}
	public String getPprice() {
		return pprice;
	}
	public void setPprice(String pprice) {
		this.pprice = pprice;
	}
	@Override
	public String toString() {
		return "Product [pname=" + pname + ", pprice=" + pprice + "]";
	}
}

<2>定义POJO类定义Bean对象

BeanConfig.java:
/**       
 * Spring3.0以JavaConfig为核心,提供使用Java类定义Bean信息的方法
 * @Configuration 指定POJO类为Spring提供Bean定义信息
 * @Bean 提供一个Bean定义信息
 */
// 代表这个Bean对象是一个Bean的配置注解
@Configuration
public class BeanConfig {
	/**
	 * 方式1:@Bean
	 * 如果没有指定name属性,则表示方法名即为对应Bean的id
	 * 此处为initCellphone
	 */
	@Bean
	public Cellphone initCellphone() {
		Cellphone cp = new Cellphone();
		cp.setCname("诺基亚");
		cp.setCprice("5000");
		return cp;
	}
	/**
	 * 方式2:@Bean("xxx")
	 * 指定name属性表示该bean对象的id为指定的内容
	 */
	@Bean(name="product")
	public Product initProduct() {
		Product p = new Product();
		p.setPname("电冰箱");
		p.setPprice("10000");
		return p;
	}
}

<3>编写测试类进行测试

8a16aead86abdb5f22df0f3ff9c5e430.png

<4>测试结果

4774addd89f470f259682147cd74890e.png

d.xml配置和注解配置综合案例

<1>dao层、Service层定义

CustomerDAO .java:
public class CustomerDAO {

}
OrderDAO .java:
public class OrderDAO {

}
CustomerService.java:
public class CustomerService {
	// 1.使用注解的方式定义OrderDAO对象
	@Autowired(required=false)
	@Qualifier("orderDAO")
	private OrderDAO orderDAO;
	
	// 2.使用xml配置方式定义Customer对象,需根据需求提供相应的构造器或setter方法
	private CustomerDAO customerDAO;
	
	public void setCustomerDAO(CustomerDAO customerDAO) {
		this.customerDAO = customerDAO;
	}

	@Override
	public String toString() {
		return "CustomerService [orderDAO=" + orderDAO + ", customerDAO=" + customerDAO + "]";
	}
}

<2>核心配置文件applicationContext.xml配置CustomerDAO

96ef041b5b6c8bb6a07bc2ac691d3db1.png

<3>编写测试文件

809fb42ffc2c744375965a075691974b.png

<4>测试结果

978abdd15d3d992993427adb36514d8d.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值