Spring学习第五天---依赖注入及高级部分

第五天

反转控制(IOC Inverse of Control)和 依赖注入

反转控制(IOC Inverse of Control)

1.控制:对成员变量赋值的控制权

2.反转控制:把对于成员变量赋值的控制权,从代码中反转到Spring工厂和配置文件完成

3.好处:解耦合

4.底层实现:工厂模式

依赖注入

1.注入:通过Spring的工厂及配置文件,为对象的成员变量赋值

2.依赖注入:当一个类需要另一个类时,就意味着依赖,一旦依赖,就可以把另一个类作为本类的成员变量,最终通过Spring配置文件注入

3.好处:解耦合

Spring工厂创建复杂对象

在这里插入图片描述

什么是复杂对象

复杂对象:值得就是不能直接通过new构造方法创建对象比如Connection,SqlSessionFactory

Spring工厂创建复杂对象的三种方式

1.FactoryBean接口

​ (1)实现FactoryBean接口

package com.spring.context.basic;

import org.springframework.beans.factory.FactoryBean;

import java.sql.Connection;
import java.sql.DriverManager;

/**
 * @author PitterWang
 * @create 2020/5/30
 * @since 1.0.0
 */
public class ConnectionFanctoryBean implements FactoryBean {
    
    


   /**
    * 业务代码
    * @return
    * @throws Exception
    */
   @Override
   public Object getObject() throws Exception {
    
    
      Class.forName("com.mysql.jdbc.Driver");
      Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo", "root", "manager1");
      return connection;
   }

   /**
    * 返回要返回的对象
    * @return
    */
   @Override
   public Class<?> getObjectType() {
    
    
      return Connection.class;
   }

   /**
    * 是否创建多个对象
    * @return
    */
   @Override
   public boolean isSingleton() {
    
    
      return false;
   }
}

​ (2)Spring配置文件的配置

<bean id = "conn" class="com.spring.context.basic.ConnectionFanctoryBean"/>

​ (3)使用

    @org.junit.Test
   public void test2(){
    
    
      ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");	@org.junit.Test
	public void test2(){
    
    
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");

		//com.mysql.jdbc.JDBC4Connection@1c39680d

		Connection connection =(Connection) applicationContext.getBean("conn");
		System.out.println(connection);

		//com.spring.context.basic.ConnectionFanctoryBean@62833051
		ConnectionFanctoryBean connectionFanctoryBean = (ConnectionFanctoryBean)applicationContext.getBean("&conn");
		System.out.println(connectionFanctoryBean);
	}
      Connection connection =(Connection) applicationContext.getBean("conn");
      System.out.println(connection);
   }

说明:

①如果获得复杂对象就直接用applicationContext.getBean(“conn”);

​ 如果想获得当前bean对象就用applicationContext.getBean("&conn");

②isSingleton方法,返回true只会创建一个复杂对象,返回false每次创建都会创建新的对象。

③Spring内部运⾏流程

 		1. 通过conn获得 ConnectionFactoryBean类的对象 ,进 ⽽通过instanceof 判断出是 FactoryBean接⼝的实现类
        2.  Spring按照规定 getObject() ---> Connection 
        3.  返回Connection

2.实例工厂

(1)创建复杂对象

package com.spring.context.basic;

import java.sql.Connection;
import java.sql.DriverManager;

/**
 *  实例工厂
 *
 * @author PitterWang
 * @create 2020/5/30
 * @since 1.0.0
 */
public class ConnectionFanctoryNewBean {
    
    

   public Connection getConnection() throws Exception {
    
    
      Class.forName("com.mysql.jdbc.Driver");
      Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo", "root", "manager1");
      return connection;
   }
}

(2)配置文件

<bean id = "fanctoryNewBean" class="com.spring.context.basic.ConnectionFanctoryNewBean"></bean>

<bean id="connew" factory-bean="fanctoryNewBean" factory-method="getConnection"/>

(3)使用

@org.junit.Test
public void test3(){
    
    
   ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");
   //com.mysql.jdbc.JDBC4Connection@7c214cc0
   Connection connection =(Connection) applicationContext.getBean("connew");
   System.out.println(connection);
}

3.静态工厂

(1)创建复杂静态方法

public static Connection getConnectionNew() throws Exception {
    
    
   Class.forName("com.mysql.jdbc.Driver");
   Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo", "root", "manager1");
   return connection;
}

(2)配置文件

    <bean id = "fanctorybb" class="com.spring.context.basic.ConnectionFanctoryNewBean" factory-method="getConnectionNew"/>

(3)使用

@org.junit.Test
public void test4(){
    
    
   ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");
   //com.mysql.jdbc.JDBC4Connection@7c214cc0
   Connection connection =(Connection) applicationContext.getBean("fanctorybb");
   System.out.println(connection);
}

创建对象次数

控制简单对象的创建次数

<bean id="pp"  scope="singleton/prototype" class="com.spring.context.basic.Persion"/>

通过scope来控制

singleton:只会创建一次默认值

prototype:每一次都会创建新的对象

控制发杂对象的创建次数

public boolean isSingleton() {
    
    
   return false;  //每一次都会创建新的
   return true;  //只会创建一次
}

Spring 创建对象总结

在这里插入图片描述

对象的生命周期

什么是生命周期

指一个对象创建、存活、消亡的一个完整过程。

了解Spring负责对象的创建、存活、销毁,了解什么周期,有利于我们使用号Spring为我们创建的对象

生命周期的三个阶段

(1)创建阶段

​ scope = “singleton”

1.Spring 工厂创建的时候,对象就同时创建
2.如果配置lazy-init="true",获取对象的同时,创建对象

​ scope = “prototype”

获取对象的同时,创建对象

(2)初始化阶段

Spring工厂在创建完对象后,调用对象的初始化方法,完成对象的初始化操作
1.根据需求,提供初始化方法,完成初始化
2.初始化方法调用是Spring工厂自动调用

提供初始化方法的两种方式

①实现InitializingBean接⼝

1.实现InitializingBean接口
2.实现afterPropertiesSet方法
public class Teacher implements InitializingBean {
	private Long id;

	private String teacherName;

	public Teacher() {
		System.out.println("Teacher~~~~~");
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getTeacherName() {
		return teacherName;
	}

	public void setTeacherName(String teacherName) {
		this.teacherName = teacherName;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("初始化~~~~~~~~~~~~");
	}
}

②对象提供一个普通方法

1.写初始化方法
	public void myInit(){
		System.out.println("初始化2~~~~~~~~~~~~");
	}
2.在配置文件种配置
    <bean id="pp111"  class="com.designpatterns.factory.test2.Teacher" init-method="myInit"/>

初始化说明:

1.如果一个对象两种方法都用了,初始化顺序是先完成InitializingBean接口方法,后自定义方法

2.注入一定反转在初始化之前

3.什么是初始化?资源初始化,比如IO,网络,数据库

(3)销毁阶段

Spring销毁对象之前,回调用对象的销毁方法,完成销毁操作
1.什么时候销毁所创建的对象?
ctx.close();的时候
2.销毁方法根据需求,定义销毁方法,完成销毁操作。调用时Spring去调用

提供销毁方法的两种方式

①实现DisposableBean接口

①对象实现DisposableBean接口
②实现destroy方法
@Override
	public void destroy() throws Exception {
		System.out.println("d销毁方法~~~~~~~~~~~~");

	}

②自定义销毁方法

	①写销毁方法
	public void myDestroy(){
		System.out.println("d销毁方法2~~~~~~~~~~~~");

	}
	②在配置文件中配置
	    <bean id="pp111"  class="com.designpatterns.factory.test2.Teacher" init-method="myInit" destroy-method="myDestroy"/>

销毁方法说明

1.销毁方法只适用于scope=“singleton”

2.销毁方法主要用于资源释放。io.close()…

配置文件可参数化

把Spring配置⽂件中需要经常修改的字符串信息,转移到⼀个更⼩的配置⽂件中

(1)提供一个小的配置文件(.properities)

名字,位置随便方

jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/demo
jdbc.username = root
jdbc.password = manager1

(2)把配置文件引入到spring配置文件中

<context:property-placeholder location="classpath:/db.properties"/>

(3)在spring文件中通过${key }获取小配置文件的对应的值

<bean id = "fanctoryNewBean" class="com.spring.context.basic.ConnectionFanctoryNewBean">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

自定义类型转换器

1.类型转换器

Spring 通过类型转换器把配置文件中字符串类型的数据,转换成了对象中成员变量的类型的数据,进而完成注入

2.自定义类型转换器

因为Spring内部没有提供特点类型转换器,所以有些转换器需要自己去定义

1.实现Converter接口,实现convert方法
public class MyDateConverter implements Converter<String, Date> {

	@Override
	public Date convert(String source) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd");
		Date parse = null;
		try {
			 parse = simpleDateFormat.parse(source);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return parse;
	}
}
2.配置文件中注册转换器
       <bean id= "myDateConverter" class="com.spring.context.basic.converter.MyDateConverter"></bean>

<!--
    id必须时conversionService
    ⽬的:告知Spring框架,我们所创建的MyDateConverter是⼀个类型转换器
-->
    <bean id = "conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <ref bean="myDateConverter"/>
            </set>
        </property>
    </bean>

后置处理Bean

(1)BeanPostProcessor,对Spring工厂所创建的对象进行再加工

(2)实现BeanPostProcessor接口,需要实现接口中的两个方法

//作用:Spring创建完对象,并进行注入后,可以运行Before方法进行加工  
//获得Spring创建好的对象,通过方法的参数最终通过返回值交给Spring框架
@Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
     
      return bean;
   }
//作⽤:Spring执⾏完对象的初始化操作后,可以运⾏After⽅法进⾏加⼯
//获得Spring创建好的对象 :通过⽅法的参数最终通过返回值交给Spring框架
   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
      
      return bean;
   }
}

(3)开发步骤

(1)后置Bean实现BeanPostProcessor接⼝

package com.spring.context.basic.beanPostProcessor;

import com.spring.context.basic.Persion;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * 〈〉
 *
 * @author PitterWang
 * @create 2020/6/2
 * @since 1.0.0
 */
public class BeanPostProcessBean implements BeanPostProcessor {
    
    

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
		if(bean instanceof Persion){
    
    
			Persion persion = (Persion) bean;
			persion.setName("wcdd");
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
		if(bean instanceof Persion){
    
    
			Persion persion = (Persion) bean;
			persion.setName("qwert");
		}
		return bean;
	}
}

(2)配置文件配置Bean

 
//配置到那个spring工厂,就会对Spring⼯⼚中所有创建的对象进⾏加⼯。
<bean class="com.spring.context.basic.beanPostProcessor.BeanPostProcessBean"/>

猜你喜欢

转载自blog.csdn.net/weixin_35133235/article/details/106603879