查看容器属性的方法_[Spring]-Spring框架-02-IOC容器

Spring框架

IOC容器

理解IOC容器和DI依赖注入

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

792c259c983d0492ee7f17406924c0a7.png

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

e5f94e5ef1546e32d4dff81213b80b26.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>查看测试结果

f76d39762f41e1f6709d93fbd65abdb8.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>编写代码获取指定对象进行测试

1135ffd362fa0ce6889c42c691526e80.png

<4>查看测试结果

b63be59a55b5b61414876418f0faf6ea.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>编写代码获取指定对象进行测试

deddf24b1121104d3c1bd6275e1e8249.png

<4>查看测试结果

d93f588add75416c0a0664b1be95f5a0.png

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

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

5b43e1715e17db19e6f1e6caa99eb3d3.png

0a51c78fb7dafcc5a10558aa2a67d5d4.png
  • singleton

41ffc13f75235b00b0c2fefa20b762d7.png
  • prototype

d40cd48be23728f848dce67d959ce31d.png

68f3bd79608ede45b23d3e410c2b5902.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测试结果:

a973ad8ed485da4592630fe80546db9e.png

Prototype测试结果:

be686362cf50f7284d04a5dd9988318a.png

Bean属性依赖注入

f26a45a58c96cb278ce4fbf1bd1e0e96.png

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

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

a.第一种构造器注入

915b4c22850e35f0036a91e335908da7.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>使用构造函数的参数类型进行注入

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

e61835cf4fa8088aabf35603b6506444.png

编写测试代码:

6907b0341b3bb91b94598a43c521e4df.png

测试结果:

bd1391d32358ed4b6616718fd2c56676.png

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

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

ab5114e86a542a9c1d39dd0afba9f1cc.png

编写测试代码:

a0e8ba4baa77727cefaf9289d0080b41.png

测试结果:

c9fab91ef5dd251c574dd36985b5b793.png

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

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

58fcffdf0bbd7408b6a47be3a839b5b0.png

编写测试代码:

7ecdc267f64544e8b047cd27e792a29e.png

测试结果:

3a52ac6e62fd4d44636984d108a7b5c4.png

b.Setter方法注入

c6c2b13fd25787b8423d94ebe1bd60ed.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配置:

7b36ac745ce6a0bfdcd41be2c4f7443f.png

代码测试:

9229dbd7dfa2f2d5d92ea6d1eef2e6b3.png

测试结果:

0c01d335706b43dddeef48cb01d37158.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配置:

280ac400da94b831c59a676e637acd34.png

代码测试:

2089b8d23e681f691bb1a9fd04ea2471.png

测试结果:

c6577bd7895b131e151a86a297102cd4.png

<3>集合属性的注入

9accaab2366ffa757e5f1a68904c29a6.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>

代码测试:

54061643c67de6d43b77b88ed4978a9a.png

测试结果:

2d876053a502e0c4772f90a040352f37.png

ebe65f74f9ab888c0daaeb31f7c9ddc3.png

<4>P命名空间的使用

4e814005c9115dce19a53da0607b947d.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">

48363684ac76b2bfde5b4aab2b0c3240.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 + "]";
	}
}

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

8dc26785f9d321ac2adae0063e1a5bdc.png

编写测试代码:

9eecb1ccdfa4b9cf03fbe860dd2d96a7.png

测试结果:

9a212ffdd867b5e154082cae96ca23b0.png

16dc14baac42c2b40114bef804ede82b.png

多个xml配置文件

4e93470a31c01bd73a55e8112fcce2ac.png

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

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

4fe3cc29b40ff766c56be079dd494140.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:

19fd909e1535ff083511dd6f216fd0cb.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的自动扫描和要扫描的包

719c921f3b1e1c722966996e5a2915bd.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 声明组件

c2d415cc8e1ebb9163a67e3890cf2d29.png

<3>测试代码

dcaae0d086186960ad82f1f174f8f51c.png

<4>测试结果

98312bcf5b223ab014fdf9740f461a24.png

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

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

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

@Repository测试

704f99705b156c4b6a2e07363107332a.png

6c868bcbfad05f789c0f0c17e6149b9d.png

测试结果:

7482e6ac232a37331c938a9ed118c509.png

@Service测试

ecc84c114105eab180c4f8c09aff66ea.png

7c0d9db1428a70bd2379d916635cfe7f.png

测试结果:

87ae59d6dcf3da2129012b80db23cd2b.png

@Controller测试

984c51cfbd0f2c4f1e5346f9e6c82dbb.png

59c4e876c929f13705bd0bb13fff908f.png

测试结果:

48d86e08a6f46811d991fd7e84729c31.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")

790bb3d743d623f7d79693e73f6a08ac.png

b.Bean的范围

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

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

489dcbd93298c82cd34d55fed225d254.png

<3>编写测试文件

b516688f979d8566ff0e9e0864dc402f.png

<4>测试结果分析

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

1860075c055c094e0b86c27f305ae337.png

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

b5d3665789347ae4c9e385d8ede373ff.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>编写测试类进行测试

142eba0e4015d22d23a7b377d3d364df.png

<4>测试结果

3cc90981dee8e73ff9280ae5ff4e5c52.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

dccce9e2ba7768afa6c9b2d72263c013.png

<3>编写测试文件

04dd219f5e1e3c5a0292a7bfeab2ca67.png

<4>测试结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值