spring学习笔记 ----- (IOC/DI)

前言:此前一直将精力放在快速输入的过程,每天学习大量的知识。虽然每天学习时间充裕,但是效率低下。究其原因,是只顾埋头输入,忘记输出。没有总结,没有自己的思考。所以,从现在开始,坚持每天输出。(Dream bigger, go higher.)

今天研究的对象是spring框架。关于spring,几乎已经统治了Javaweb开发。学习java,spring就必须掌握。

今天关注的主要的对象是其中之一 IOC:

1  IOC作用

      通过spring提供的IOC容器,可以将对象间的依赖关系交由spring进行控制,避免代码所造成的过度程序耦合。可以让程序员更加专注于上层的应用,而不必考虑单例模式类,属性文件解析等底层的需求。

2  程序之间的耦合?

/**
* 客户的业务层实现类
*/

public class CustomerServiceImpl implements Customer{

      private  CustomerDao dao = new CustomerServiceImpl();
}

//业务层调用持久层,并且此时业务层依赖持久层的接口和实现类,若没有实现层实现类,编译将不能通过

再比如,使用数据库jdbc时,

public Class Demo{


    //当需要更换数据库品牌时,就需要更换源码来修改数据库的驱动。
    public static void main(String[] args){
            //DriverManager.registerDriver(new com.mysql.jdbc.Driver());
            Class.forName("com.mysql.jdbc.Driver");

        
    }

}

3  解决耦合的思路

      * 当在jdbc时,可以通过反射来注册实现类:

Class.forName("com.mysql.jdbc.Driver");

这样的好处就是,我们的类中不在依赖具体的驱动类。但此时,我们反射类对象的全限定类名字符串在java类中写死了,一旦改也需要修改源码。

解决这个问题,可以使用配置文件进行配置。

     * 工厂模式解耦   

      实际开发中,可以将dao service action对象使用配置文件配置起来,当启动服务器应用时进行加载,通过读取配置文件,将这些对象创建并保存起来,以后使用时,直接可以使用。

IOC -- 控制反转( 工厂 + 反射 + 配置文件 )

上述的解耦合思路可以分为:

    * 存在哪里?

      分析:由于存在很多对象,必须需要集合来进行存储,Map List 可供选择。一般情况下,我们会选择map(因为需要查找)。所以,当应用加载时,将创建一个map,用于存放dao,service,dao对象。这个map即被称之为容器。

    * 工厂?

      工厂就是负责给我们从容器中获取指定对象的类,这时候我们获取对象的方式发生了改变。

      以前我们都是采用new的方式,主动获取对象;当有工厂时,直接从工厂中获取。有工厂为我们查找或者创建对象,是被动的。这种被动接受的方式获取对象的思想就是控制反战,也即spring框架的核心之一。

<!-- 
	
		1: 基本配置
		   1) bean标签: 指定要创建的实体类
				id属性: 可以为任意值  但是在整个配置文件中唯一
				class属性: 要实例化类的全限定名
	
	 -->
	 <!-- <bean id="user" class="com.spring.demo.User"></bean> --> 
	
	<!-- 
		   2) scope属性: 范围
			    singleton: 单实例 默认值
			    	 如果是单实例,配置文件文件只要一加载  就会创建对象 放在spring容器 (map<id,对象>)
			    	 当从spring容器取的时候(getBean),所用人用的都是同一个对象
			    prototype: 多实例
				         如果是多实例,配置文件加载,不创建对象
				         当getbean的时候,getbean一次创建一次 放在容器中
		<bean id="user" class="com.spring.demo.User" scope="singleton" ></bean>
		<bean id="user" class="com.spring.demo.User" scope="prototype" ></bean>

		用途:
		action: prototype
		service/dao: singleton
		
		
		singleton 与 prototype创建的的对象销毁时间
			singleton的对象当spring容器关闭 对象销毁
			prototype的对象 长时间不用自动被垃圾回收机制给回收了

		3)	init-method:指定初始化方法
		    destory-method:指定销毁方法	
	 -->
	<!-- <bean id="user" class="com.spring.demo.User" scope="prototype" init-method="init" destroy-method="destory"></bean> -->
   
   	<!-- 
   		 2、 import:导入外部的配置文件
   		 	 resource:外部配置文件的地址

   			web: 所有在web层创建的对象   applicationContext_web.xml
   			service:所有在service层创建的对象   applicationContext_service.xml
   			dao:所有在dao层创建的对象   applicationContext_dao.xml
   			
   			<import resource="applicationContext_web.xml"/>
   			<import resource="applicationContext_service.xml"/>
   			<import resource="applicationContext_dao.xml"/>	

   			<import resource="applicationContext_user.xml"/> 	
   	 -->
   		
   		
   	<!-- bean的三种创建方式
   		 无参构造方式
   		 静态工厂方式
   		 实例工厂方式
   	
   	  -->
   	  <!-- 无参构造方式 
   	  	<bean id="user" class="com.spring.demo.User"></bean>
   	  -->	
   	  
   	  <!-- 静态工厂方式
   	  		  条件:需要有一个工厂类 在这个工厂类中还需要有一个静态方法
   	  		 <bean id="user" class="com.spring.demo.utils.BeanFactory" factory-method="createUser"/> 
   	   -->
   	  
   	  <!-- 实例工厂
   	  		  条件:需要有一个工厂类 在这个工厂类中还需要有一个普通方法
   	  		  <bean id="beanFactory" class="com.spring.demo.utils.BeanFactory"></bean>
   	   <bean id="user" factory-bean="beanFactory" factory-method="createUser"></bean>
   	   -->

DI -- 依赖注入(IOC的具体实现方式)

<!-- 
   	DI的注入方式:
   	   1 构造器的方式
   			条件:需要有参构造方法
   	
   	 -->
   	<!--  <bean id="car" class="com.spring.demo.serviceImpl.CarImpl">
   	 		构造器的方式 
   	 			 name:要赋值的属性名
   	 			 value:要赋的值 (针对的是基本类型和String类型)
   	 			 ref: 针对的是对象类型
   	 		
   	 		<constructor-arg name="name" value="Tesla"></constructor-arg>
   	 		<constructor-arg name="price" value="500000"></constructor-arg>
   	 </bean> -->
   	 
<!-- 
   	DI的注入方式:
   		2 set属性的方式
   			条件:属性必须要有set方法
   			name:要赋值的属性名
   	 		value:要赋的值 (针对的是基本类型和String类型)
   	 		ref: 针对的是对象类型 -- 指向的是spring中bean的id名  
   				   	     
   	
   	 -->
   	 <!-- <bean id="person" class="com.spring.demp.serviceImpl.PersonImpl">
   	 		set属性的方式
   	 		<property name="name" value="jorgen"></property>
   	 		<property name="car" ref="car"></property>
   	 </bean> -->
   		
   	
<!-- 
	 DI的注入方式:
	   	3 p名称空间的方式
	   		条件: 在配置文件中有p的名称空间 (底层set方式  属性还是得有set方法)
   	     		语法:
					<bean p:属性名="属性值" p:属性名-ref="bean的id对象值" >
	   	 -->
	   	 <!-- <bean id="person" class="com.spring.demo.serviceImpl.PersonImpl" p:name="polaris" p:car-ref="car"></bean> -->
	   	 
	   	 
	   	 <!-- DI:复杂属性注入 -->
	   	 <bean id="collBean" class="com.spring.demo.CollectionBean">
	   	 	 <property name="date">
	   	 	 		<!-- 数组类型 -->
	   	 	 		<list>
	   	 	 			<value>year</value>
	   	 	 			<value>month</value>
	   	 	 			<value>day</value>
	   	 	 		</list>
	   	 	 </property>
	   	 	 
	   	 	 <property name="number">
	   	 	 		<!-- list类型  -->
	   	 	 		<list>
	   	 	 			<value>111</value>
	   	 	 			<value>222</value>
	   	 	 			<ref bean="car"/>
	   	 	 		</list>
	   	 	 </property>
	   	 	 
	   	 	 <property name="mapBean">
	   	 	 	<!-- map -->
	   	 	 	<map>
	   	 	 		<entry key="k1" value="a"></entry>
	   	 	 		<entry key="k2" value="b"></entry>
	   	 	 		<entry key="k3" value-ref="car"></entry>
	   	 	 	</map>
	   	 	 </property>
	   	 	 
	   	 	 <property name="properties">
	   	 	 	<!-- properties类型 -->
	   	 	 	<props>
	   	 	 		<prop key="username">root</prop>
	   	 	 		<prop key="password">1234</prop>
	   	 	 	</props>
	   	 	 </property>
	   	 </bean>

     总结完全部xml的方式配置后,一般企业开发都是采用半注解半xml配置方式

   一般第三方的类采用xml方式,本地的类用注解方式。

* 注解方式

   配置注解扫描器
  <context:component-scan base-package="com.spring"></context:component-scan>

@Component("bean的id值") 定义在类上 注解扫描器就会创建该类的实例对象 放在spring容器中
    注意:spring发布公告, @Component这个注解不维护了,要维护这个注解下面衍生出的3个注解
              @Controller("bean的id值") 针对的就是web层  

              @Service("bean的id值")    针对的是service层

              @Repository("bean的id值") 针对的是dao层
             


//@Component("userService") 
//<bean id="userService"  class="com.spring.demo.serviceimpl.UserServiceImpl">
@Service("userService")
public class UserServiceImpl implements UserService
{...}

@Value("属性值") 定义在属性字段上 针对的是基本类型和String类型
     如果使用了这个注解 该属性的set方法可以省略不写

@Value("jorgen")
private String name;

 @Autowired     定义在属性字段上的 针对的是对象类型
      如果定义在了那个对象类型的属性身上 会自动去spring容器中找该类型的实例对象给赋值

@Qualifier("userDaoxxx")定义在属性字段上的 指定用该类型的哪个id名称的实例对象

      注意: @Qualifier要想使用 必须结合 @Autowired 一起使用

   @Resource(name="userDao")
   @Autowired+@Qualifier("userDao")

//@Autowired // 自动去spring容器中找有没有该类型(UserDao)的实例对象 如果有直接赋值
//@Qualifier("userDao") // 指定用该类型的哪个名称的实例对象
@Resource
private UserDao userDao;

了解的注解:
    @Scope("singleton"或则prototype)  定义在类上的 指定当前类是单实例还是多实例

    @PostConstruct  定义在方法上  配置初始化方法

    @PreDestroy     定义在方法上 配置销毁的方法

猜你喜欢

转载自blog.csdn.net/Jorgen_s/article/details/89351705