Spring学习笔记(一) IOC ,bean的配置

最近看到一些帖子 很多内容不明白 应该开始理解一下基础,不能只会用 所以博主决定重学一下SSM 和一些基础重点。

目录

   什么是IOC :不是技术,是一种设计思想!!!!!  

 Bean的配置和获取方式

配置bean

配置bean的属性

内部bean  可以不配置id ,这样其它的bean就无法引用的.

给bean对象的集合类型属性赋值 (这里的集合看成bean的一个属性即可)

util名称空间创建list集合

静态工厂创建bean

实例工厂

通过FactoryBean获取bean对象(重点/后面要用)

bean配置信息重用(继承)

bean创建的顺序问题

bean对象的单例和多实例(重点)

配置有生命周期的bean

 配置bean的后置处理器 (有点类似AOP切面编程)

通过属性文件给bean注入值

  Spring是什么?

  Spring是一个轻量级框架集合,是业务逻辑层和其他各层的松耦合问题。

  Spring有两个核心的概念: IOCAOP   (还有一个JdbcTemplate 一种管理数据库的机制)

  IOC  (Inversion Of Control控制反转

   什么是IOC不是技术,是一种设计思想!!!!!  

    传统开发:需要自己在程序中new对象来使用

使用IOC容器后: 对象都在IOC容器中创建 不需要你手动创建   

 Bean的配置和获取方式

这里我又去重新看了一下Bean的规范:

(JavaBean实际上是指一种特殊的Java类,它通常用来实现一些比较常用的简单功能,并可以很容易的被重用或者是插入其他应用程序中去。所有遵循“一定编程原则”的Java类都可以被称作JavaBean。

JavaBean是一个遵循特定写法的Java类,是一种Java语言编写的可重用组件,它的方法命名,构造及行为必须符合特定的约定:

1、这个类必须具有一个公共的(public)无参构造函数;
2、所有属性私有化(private);
3、私有化的属性必须通过public类型的方法(getter和setter)暴露给其他程序,并且方法的命名也必须遵循一定的命名规范。 
4、这个类应是可序列化的。(比如可以实现Serializable 接口,用于实现bean的持久性)

JavaBean在Java EE开发中,通常用于封装数据,对于遵循以上写法的JavaBean组件,其它程序可以通过反射技术实例化JavaBean对象(内省机制),并且通过反射那些遵循命名规范的方法,从而获知JavaBean的属性,进而调用其属性保存数据。

因为这些要求主要是靠约定而不是靠实现接口,所以许多开发者把JavaBean看作遵从特定命名约定的POJO。(可以这么理解,POJO按JavaBean的规则来,就可以变成JavaBean)。

简而言之,当一个POJO可序列化,有一个无参的构造函数,使用getter和setter方法来访问属性时,他就是一个JavaBean。(没毛病!)
 

此段摘要来自:https://blog.csdn.net/chenchunlin526/article/details/69939337

配置bean

  • 基于xml配置Bean
  • 使用注解定义Bean
  • 基于java类提供Bean定义信息    

具体操作不做说明 需要了解 传送门

本文用的bean

获取bean的方法


ApplicationContext applicationContext =  new ClassPathXmlApplicationContext("beans.xml");
 Object bean = applicationContext.getBean("这里是bean的ID");

配置bean的属性

1.通过构造器来获取

第一种是通过<property>标签
<bean id="monster01" class="com.fy.spring.bean.Monster" >
 	<property name="id" value="100" />
 	<property name="nickname" value="~牛魔王~" />
 	<property name="skill" value="芭蕉扇" />
 </bean>



第二种是通过<constructor-arg>标签 

   方式1: 同index 来指定参数位置
 <bean id="monster02" class="com.fy.spring.bean.Monster">
 	<constructor-arg index="0" value="200" />
 	<constructor-arg index="1" value="白骨精" />
 	<constructor-arg index="2" value="吃人" />
 </bean>
  
 方式2: 用类型来来指定参数位置

<bean id="monster03" class="com.fy.spring.bean.Monster">
 	<constructor-arg  type="Integer" value="300" />
 	<constructor-arg  type="String" value="红孩儿" />
 	<constructor-arg  type="String" value="三位真火" />
 </bean>

2.通过P标签获取

  <bean id="monster04" class="com.fy.spring.bean.Monster"

  p:id="400"
  p:nickname="蜘蛛精"
  p:skill="吐口水"

  />

内部bean  可以不配置id ,这样其它的bean就无法引用的.

  <!-- 配置一个master bean对象, 含有内部bean -->
  <bean id="master02" class="com.fy.spring.bean.Master">
  <property name="name" value="地藏王" />
  <property name="monster" ref="monster02" /> //ref 是引用的意思
  <property name="monster2">
   <bean class="com.fy.spring.bean.Monster">
   	 <property name="id" value="500"/>
   	 <property name="nickname" value="谛听"/>
   	 <property name="skill" value="顺风耳"/>
   </bean>
  </property>
  </bean>

给bean对象的集合类型属性赋值 (这里的集合看成bean的一个属性即可)

 <!-- 配置一个master bean对象 ,还有List集合属性 -->
  <bean id="master03" class="com.fy.spring.bean.Master">
  <property name="name" value="地藏王" />
  <property name="monster" ref="monster02" />
  <property name="monster2" ref="monster01" />
  <property name="monsterList">
  <list>
  	<ref bean="monster03"/>
  	<ref bean="monster04"/>
  </list>
  </property>
  </bean>

  
  
  <!-- 配置一个master bean对象 ,还有map集合属性 -->
  <bean id="master04" class="com.fy.spring.bean.Master">
  <property name="name" value="~地藏王~" />
  <property name="monster" ref="monster02" />
  <property name="monster2" ref="monster01" />
  <property name="map">
  
  <map>
  	<entry>
  		<key>
  			<value>monstermap01</value>
  		</key>
  		<ref bean="monster03"/>
  	</entry>
  		<entry>
  		<key>
  			<value>monstermap02</value>
  		</key>
  		<ref bean="monster04"/>
  	</entry>
  </map>
  </property>
  </bean>
  
  
  <!-- 配置一个master bean对象 ,有properties集合属性 -->
  <!--说明一下Properties 集合的特点
            (1).这个Properties 是 Hashtable的子类 , 是key-value的形式
            (2).key 是 string 而  value 也是 string   -->

  <bean id="master05" class="com.fy.spring.bean.Master">
  <property name="name" value="~地藏王~" />
  <property name="monster" ref="monster02" />
  <property name="monster2" ref="monster01" />
  <property name="ps">
  <props>
  	<prop key="prokey01">牛魔王</prop>
  	<prop key="prokey02">白骨精</prop>
  </props>
  </property>
  </bean>

util名称空间创建list集合

<util:list id="myList">
  	<value>list值1-string</value>
  	<value>list值2-string</value>
  </util:list>

获取方法: List<String> listStr = (List<String>) applicationContext.getBean("myList");
		
		 for (String string : listStr) {
			System.out.println("val=" + string);
		 }

级联属性赋值(这个可能用的机会很少)

 <bean id="myDog" class="com.fy.spring.bean.Dog"/>
  <bean id="myBoy" class="com.fy.spring.bean.Boy">
  	<property name="name" value="tom" />
  	<property name="dog" ref="myDog"/>
  	<!-- 级联属性赋值 -->
  	<property name="dog.name" value="哈趴狗"/>
  </bean>

静态工厂创建bean


需要先创建一个静态工厂
public class MyStaticFactory {

	private static HashMap<String,Monster> map;
	
	//静态块
	static{
		map = new HashMap<String, Monster>();
		map.put("monsterkey01", new Monster(700, "小鱼怪", "喝水"));
		map.put("monsterkey02", new Monster(800, "大鱼怪", "喝很多水"));
	}
	
	public static Monster getMonster(String key){
		return map.get(key);
	}
	
	
}

  <!-- 通过静态工厂获取bean对象 -->
  <bean id="myMonster" class="com.itbull.spring.bean.MyStaticFactory" 
  factory-method="getMonster">
  <constructor-arg  value="monsterkey02"/>
  </bean>

实例工厂


public class MyInstaneFactory {

	private  HashMap<String,Monster> map;
	
	//代码块
	{
		map = new HashMap<String, Monster>();
		map.put("monsterkey01", new Monster(900, "~小鱼怪~", "喝水"));
		map.put("monsterkey02", new Monster(1000, "~大鱼怪~", "喝很多水"));
	}
	
	public  Monster getMonster(String key){
		return map.get(key);
	}
	
	
}

  <!-- 通过实例工厂获取bean对象 -->
  <bean id="myInstaneFactory" 
     class="com.fy.spring.bean.MyInstaneFactory"/>
  <!-- 从myInstaneFactory获取 -->
  <bean id="myMonster2" factory-bean="myInstaneFactory" 
      factory-method="getMonster" >
  <constructor-arg  value="monsterkey01"/>
  </bean>

通过FactoryBean获取bean对象(重点/后面要用)

public class MyFactoryBean implements FactoryBean<Monster>{

	private String keyVal;
	private Map<String,Monster> map;
	
	{
		map = new HashMap<String, Monster>();
		map.put("monsterkey01", new Monster(900, "~小猫怪~", "抓老鼠"));
		map.put("monsterkey02", new Monster(1000, "~大猫怪~", "抓很多老虎"));
	}


	/**
	 * 这个是用于接收你需要哪个key对应的monster
	 * @param keyVal
	 */
	public void setKeyVal(String keyVal) {
		System.out.println("keyval = " + keyVal);
		this.keyVal = keyVal;
	}

	/**
	 * 就是返回的bean
	 */
	@Override
	public Monster getObject() throws Exception {
		System.out.println("getobject key" + keyVal);
		// TODO Auto-generated method stub
		return map.get(keyVal);
	}

	/**
	 * 返回的bean对象的类型
	 */
	@Override
	public Class<?> getObjectType() {
		// TODO Auto-generated method stub
		return Monster.class;
	}

	/**
	 * 是否以单例的方式返回 。
	 */
	@Override
	public boolean isSingleton() {
		// TODO Auto-generated method stub
		return true;
	}

}

  <!-- 使用factoryBean获取设置bean -->
  <bean id="myMonster3" class="com.fy.spring.bean.MyFactoryBean">
  <property name="keyVal" value="monsterkey02" />
  </bean>

bean配置信息重用(继承)

 <!-- 希望创建一个monster对象,他的值和 monster01一样
 	注意 : 如果我们希望某个bean是值用于继承,本身不能被实例化,则将这个bean 设置为  abstract=ture
 -->
 <bean id="monster10" class="com.fy.spring.bean.Monster" parent="monster20"/>

bean创建的顺序问题

在spring的ioc容器, 在默认情况下是按照配置的顺序来创建的比如
<bean id="student01" class="com.fy.bean.Student" />
<bean id="department01" class="com.fy.bean.Department" />

会先创建student01这个bean对象,然后创建department01这个bean对象,
但是,如果这样配置就会先创建department01bean,再创建student01这个bean.

<bean id="student01" class="com.fy.bean.Student"  depends-on="department01"/>
<bean id="department01" class="com.fy.bean.Department" />

bean对象的单例和多实例(重点)

不了解单例和多例的看下这个 传送门

单例打印出来的Hashcode是同一个地址

在spring的ioc容器, 在默认情况下是按照单例创建的,即配置一个bean对象后,ioc容器只会创建一个bean实例。

如果,我们希望ioc容器配置的某个bean对象,是以多个实例形式创建的则可以通过配置 scope="prototype" 来指定

细节说明:
默认是单例,当 <bean  scope="prototype" > 设置为多实例机制
设置为 scope="prototype" 后,该bean是在getBean时才创建。

配置有生命周期的bean

public class Cat {

	private String name;
	
	

	public String getName() {
		return name;
	}

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

	public Cat() {
		System.out.println("cat被出生了了!");
	}
	
	//初始化的方法 
	public void init() {
		// TODO Auto-generated method stub
		System.out.println("小猫被初始化, 给他取名  " + this.name);

	}
	

	public Cat(String name) {
		super();
		this.name = name;
	}
	
	public void play(){
		System.out.println(this.name + " 快乐的玩耍");
	}
	//销毁方法
	public void destory() {
		// TODO Auto-generated method stub
		System.out.println(this.name + "活了 100岁,安息..");
	}
}


在spring的ioc容器,配置有生命周期的bean 即 创建/初始化/销毁。
  <bean id="myCat2" class="com.fy.spring.bean.Cat" 
     init-method="init" destroy-method="destory">
  	<property name="name" value="~糖宝~"/>
  </bean>
1.创建就是调用bean的构造函数,初始化就是 init方法(名字是程序员来确定的,根据你的业务逻辑来确定你需要什么时候进行初始化)。

2.销毁方法就是当关闭容器时,才会被销毁

测试结果

	public void test12() {
		
		Cat cat = (Cat) applicationContext.getBean("myCat2");
		cat.play();
		//关闭容器..
		ConfigurableApplicationContext cac = 
				(ConfigurableApplicationContext) applicationContext;
		cac.close();
		System.out.println("程序没有退出 ");
		
		
	}


cat被出生了了!
小猫被初始化, 给他取名  ~糖宝~
~糖宝~ 快乐的玩耍
~糖宝~活了 100岁,安息..
程序没有退出 

 配置bean的后置处理器 (有点类似AOP切面编程)

  实现BeanPostProcessor接口

public class MyBeanPostProcessor implements  BeanPostProcessor{

	
	@Override
	public Object postProcessBeforeInitialization(Object bean, String name)
			throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("初始化方法前被调用!" + bean.getClass());
		return bean;
	}
	
	@Override
	public Object postProcessAfterInitialization(Object bean, String name)
			throws BeansException {
		System.out.println("初始化方法后被调用!");
		// TODO Auto-generated method stub
		return bean;
	}

	

}

在xml文件中配置

<!-- 配置自己的后置处理器 -->
<bean id="myBeanPostProcessor" class="com.fy.spring.bean.MyBeanPostProcessor"/>

通过属性文件给bean注入值

<!-- 引入我们的my.properties文件 引入context名字空间-->
  <context:property-placeholder location="classpath:my.properties"/>
  <!-- 通过外部的一个属性文件来初识化一个monster -->
  <bean id="monster99" class="com.itbull.spring.bean.Monster">
  <property name="id" value="${monster.id}" />
  <property name="nickname" value="${monster.name}" />
  <property name="skill" value="${monster.skill}" />
  </bean>
</beans>



文件类容 
monster.id=1000
monster.name=\u72d0\u72f8\u7cbe
monster.skill=\u7f8e\u4eba\u8ba1

猜你喜欢

转载自blog.csdn.net/ly610501737/article/details/86601557