zoukankan      html  css  js  c++  java
  • Spring核心概念之Ioc

    一、初识Spring之Ioc

    Spring是一个轻量级的企业级开源框架,Spring框架的核心是一个Ioc容器。

    Ioc (Inversion of Control)又称"控制反转",是面向对象编程中的一种设计原则,用来降低程序代码之间的耦合度。

    实战演练:使用Spring Ioc实现业务层和数据访问层解耦合。

    1.定义数据访问层接口:UserDao

    package com.jbit.fsd.dao;
    
    import java.util.List;
    
    import com.jbit.fsd.entity.User;
    
    public interface UserDao {
    
    	public List<User> getAll();
    }
    

    2.定义了业务访问层接口:UserService

    package com.jbit.fsd.service;
    
    import java.util.List;
    
    import com.jbit.fsd.entity.User;
    
    public interface UserService {
    
    	public List<User> getAll();
    }
    

    3.定义了数据访问层接口实习类:UserDaoImpl

    package com.jbit.fsd.dao.impl;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import com.jbit.fsd.dao.UserDao;
    import com.jbit.fsd.entity.User;
    
    public class UserDaoImpl implements UserDao {
    
    	@Override
    	public List<User> getAll() {
    		//操作数据库读到所有数据
    		List<User> list=new ArrayList<User>();
    		list.add(new User());
    		list.add(new User());
    		list.add(new User());
    		return list;
    	}
    
    }
    

    4.定义数据访问层接口实现类:UserServiceImpl

    package com.jbit.fsd.service.impl;
    
    import java.util.List;
    
    import com.jbit.fsd.dao.UserDao;
    import com.jbit.fsd.entity.User;
    import com.jbit.fsd.service.UserService;
    
    public class UserServiceImpl implements UserService{
    	private UserDao dao;
    	//通过spring注入进来
    	public void setDao(UserDao dao) {
    		this.dao = dao;
    	}
    
    	@Override
    	public List<User> getAll() {
    		// TODO Auto-generated method stub
    		return dao.getAll();
    	}
    
    }
    

    5.在spring配置文件中配置Bean并注入业务实现类UserServiceImpl

    <?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:aop="http://www.springframework.org/schema/aop"
    		xmlns:tx="http://www.springframework.org/schema/tx"
    		xsi:schemaLocation="
    			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    		<!-- 以面向接口思想编程实现解耦和 -->
              <!-- class为bean的全类名,通过反射在IOC容器中创建bean,所有要求bean中必须有无参的构造方法 --> <bean id="userDao" class="com.jbit.fsd.dao.impl.UserDaoImpl"> </bean> <bean id="userServiceImpl" class="com.jbit.fsd.service.impl.UserServiceImpl"> <!-- 需要注意是是这里调用setDao()方法 --> <property name="dao" ref="userDao"></property> <!-- 属性注入 --> </bean> </beans>

    6.测试类入口:package com.jbit.fsd.test;

    
    import java.util.List;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.jbit.fsd.dao.UserDao;
    import com.jbit.fsd.entity.User;
    import com.jbit.fsd.service.UserService;
    
    public class Test {
    
    	/**
    	 * 
    	 * Description:
    	 * @param 
    	 * @author xiazhongwei
    	 * @data 2016:下午12:18:37
    	 * @return
    	 */
    	public static void main(String[] args) {
    		ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
    		UserService service=(UserService) ac.getBean("userServiceImpl");
    		List<User> list=service.getAll();
    		System.out.println(list.size()+"********************");
    	}
    }
    

    加载Spring配置文件亦可以使用BeanFactory:

    Rosource resource = new ClassPathResource("applicationContext.xml");

    BeanFactory factory = new XmlBeanFactory(resource);

    factory.getBean("id",Class);//根据名字和类型查找

    上面的小例子需要Spring核心jar的支持:可到官网下载:

    spring-core.xxx.jar

    spring-beans-xxx.jar

    commons-logging.xxx.jar

    如果使用ApplicationContext加载配置文件需要

    spring-context.xxx.jar

    spring-expression.xxx.jar

    说明:

    1.Spring为dao属性赋值是通过setDao()方法实现的,而非直接为dao属性赋值,若属性为dao,但是setter方法为setUserDao,Spring配置文件应该写成name="userDao",而非name="dao",是用了反射机制Class.forName(class).newInstance(),为接口注入实现类;

    2.除了使用ApplicationContext及其实现类,还可以通过BeanFactory接口实现类对Bean组件实施管理,ApplicationContext建立在BeanFactory的基础之上,可以对企业级开发提供更全名的支持。

    使用上面的方法通过spring的setter访问器实现对属性的赋值,这种方法称设置注入,除此之外,spring还提供了通过构造方法赋值,这种称构造注入

    定义业务实现类UserServiceImplByConstructor

    package com.jbit.fsd.service.impl;
    
    import java.util.List;
    
    import com.jbit.fsd.dao.UserDao;
    import com.jbit.fsd.entity.User;
    import com.jbit.fsd.service.UserService;
    
    public class UserServiceImplByConstructor implements UserService {
    
    	private UserDao dao;
    	// 定义有参的构造方法JVM不会自定义无参的构造方法,需要手动加入
    	public UserServiceImplByConstructor(){
    	}
    	// 用于为dao属性赋值的构造方法
    	public UserServiceImplByConstructor(UserDao dao){
    		this.dao = dao;
    	}
    	@Override
    	public List<User> getAll() {
    		return dao.getAll();
    	}
    }
    

    spring配置文件中的配置:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!--
      - Application context definition for JPetStore's business layer.
      - Contains bean references to the transaction manager and to the DAOs in
      - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation").
      -->
    <beans xmlns="http://www.springframework.org/schema/beans"
    		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    		xmlns:aop="http://www.springframework.org/schema/aop"
    		xmlns:tx="http://www.springframework.org/schema/tx"
    		xsi:schemaLocation="
    			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    		<!-- 以面向接口思想编程实现解耦和 -->
    	<bean id="userDao" class="com.jbit.fsd.dao.impl.UserDaoImpl">
    	</bean>
    	<bean id="userServiceImplByConstructor" class="com.jbit.fsd.service.impl.UserServiceImplByConstructor">
    		<!-- 通过定义的单参数构造为业务层的dao属性赋值 -->
    		<constructor-arg>
    			<!-- 引用id为userDao的对象为dao属性赋值 -->
    			<ref bean="userDao"/>
    		</constructor-arg>
    	</bean>
    	
    </beans>
    

    说明:一个<constructor-arg>元素表示一个构造参数,且使用时不区分顺序,当构造方法的参数出现混淆,无法区分时,可以通过<constructor-arg>元素的index属性来指定该参数的位置索引,位置从0开始,<constructor-arg>元素还提供了type属性用来指定参数的类型,避免字符串和基本类型的混淆。

    抽象Bean的定义:

    如果定义bean的属性abstract属性为true的bean,这样的bean不能被IOC容器实例化,只用来被继承配置。若一个bean的class属性没有指定,那么该bean必须是一个抽象bean。

    bean配置的继承:使用bean的parent属性指定继承那个bean的配置。并不是bean元素里的所有属性都会被继承,比如:autowire,abstract等。Spring允许通过depends-on属性设置Bean的前置依赖Bean,会在本bean实例化之前创建好,如果有多个依赖bean可以使用逗号分开配置bean的名称。

    <?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:util="http://www.springframework.org/schema/util"
    	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
    		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    	
    	<!-- 配置一个 bean -->
    	<bean id="helloWorld" class="com.atguigu.spring.helloworld.HelloWorld">
    		<!-- 为属性赋值 -->
    		<property name="user" value="Jerry"></property>
    	</bean>
    	
    	<!-- 配置一个 bean -->
    	<bean id="helloWorld2" class="com.atguigu.spring.helloworld.HelloWorld">
    		<!-- 为属性赋值 -->
    		<!-- 通过属性注入: 通过 setter 方法注入属性值 -->
    		<property name="user" value="Tom"></property>
    	</bean>
    	
    	<!-- 通过构造器注入属性值 -->
    	<bean id="helloWorld3" class="com.atguigu.spring.helloworld.HelloWorld">
    		<!-- 要求: 在 Bean 中必须有对应的构造器.  -->
    		<constructor-arg value="Mike"></constructor-arg>
    	</bean>
    	
    	<!-- 若一个 bean 有多个构造器, 如何通过构造器来为 bean 的属性赋值 -->
    	<!-- 可以根据 index 和 value 进行更加精确的定位. (了解) -->
    	<bean id="car" class="com.atguigu.spring.helloworld.Car">
    		<constructor-arg value="KUGA" index="1"></constructor-arg>
    		<constructor-arg value="ChangAnFord" index="0"></constructor-arg>
    		<constructor-arg value="250000" type="float"></constructor-arg>
    	</bean>
    	
    	<bean id="car2" class="com.atguigu.spring.helloworld.Car">
    		<constructor-arg value="ChangAnMazda"></constructor-arg>
    		<!-- 若字面值中包含特殊字符, 则可以使用 DCDATA 来进行赋值. (了解) -->
    		<constructor-arg>
    			<value><![CDATA[<ATARZA>]]></value>
    		</constructor-arg>
    		<constructor-arg value="180" type="int"></constructor-arg>
    	</bean>
    	
    	<!-- 配置 bean -->
    	<bean id="dao5" class="com.atguigu.spring.ref.Dao"></bean>
    
    	<bean id="service" class="com.atguigu.spring.ref.Service">
    		<!-- 通过 ref 属性值指定当前属性指向哪一个 bean! -->
    		<property name="dao" ref="dao5"></property>
    	</bean>
    	
    	<!-- 声明使用内部 bean -->
    	<bean id="service2" class="com.atguigu.spring.ref.Service">
    		<property name="dao">
    			<!-- 内部 bean, 类似于匿名内部类对象. 不能被外部的 bean 来引用, 也没有必要设置 id 属性 -->
    			<bean class="com.atguigu.spring.ref.Dao">
    				<property name="dataSource" value="c3p0"></property>
    			</bean>
    		</property>
    	</bean>
    	
    	<bean id="action" class="com.atguigu.spring.ref.Action">
    		<property name="service" ref="service2"></property>
    		<!-- 设置级联属性(了解) -->
    		<property name="service.dao.dataSource" value="DBCP2"></property>
    	</bean>
    	
    	<bean id="dao2" class="com.atguigu.spring.ref.Dao">
    		<!-- 为 Dao 的 dataSource 属性赋值为 null, 若某一个 bean 的属性值不是 null, 使用时需要为其设置为 null(了解) -->
    		<property name="dataSource"><null/></property>
    	</bean>
    	
    	<!-- 装配集合属性 -->
    	<bean id="user" class="com.atguigu.spring.helloworld.User">
    		<property name="userName" value="Jack"></property>
    		<property name="cars">
    			<!-- 使用 list 元素来装配集合属性 -->
    			<list>
    				<ref bean="car"/>
    				<ref bean="car2"/>
    			</list>
    		</property>
    	</bean>
    	
    	<!-- 声明集合类型的 bean -->
    	<util:list id="cars">
    		<ref bean="car"/>
    		<ref bean="car2"/>
    	</util:list>
    	
    	<bean id="user2" class="com.atguigu.spring.helloworld.User">
    		<property name="userName" value="Rose"></property>
    		<!-- 引用外部声明的 list -->
    		<property name="cars" ref="cars"></property>
    	</bean>
    	
    	<bean id="user3" class="com.atguigu.spring.helloworld.User"
    		p:cars-ref="cars" p:userName="Titannic"></bean>
    		
    	<!-- bean 的配置能够继承吗 ? 使用 parent 来完成继承 -->	
    	<bean id="user4" parent="user" p:userName="Bob"></bean>
    	
    	<bean id="user6" parent="user" p:userName="维多利亚"></bean>
    	
    	<!-- 测试 depents-on -->	
    	<bean id="user5" parent="user" p:userName="Backham" depends-on="user6"></bean>
    	
    </beans>
    

      

    二、不同类型参数的注入方法

    1.注入直接量(基本类型、字符串)

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!--
      - Application context definition for JPetStore's business layer.
      - Contains bean references to the transaction manager and to the DAOs in
      - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation").
      -->
    <beans xmlns="http://www.springframework.org/schema/beans"
    		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    		xmlns:aop="http://www.springframework.org/schema/aop"
    		xmlns:tx="http://www.springframework.org/schema/tx"
    		xsi:schemaLocation="
    			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    		<!-- 以面向接口思想编程实现解耦和 -->
    	<bean id="userDao" class="com.jbit.fsd.dao.impl.UserDaoImpl">
    	</bean>
    	<bean id="userServiceImpl" class="com.jbit.fsd.service.impl.UserServiceImpl">
    		<!-- 需要注意是是这里调用setDao()方法 -->
    		<property name="dao" ref="userDao"></property>  <!-- 属性注入 -->
    	</bean>
    	<bean id="userServiceImpl" class="com.jbit.fsd.service.impl.UserServiceImpl">
    		<property name="username">
    		</property>  
    			<!-- 注入直接量 -->
    			<value>张三</value>
    	</bean>
    	<bean id="userServiceImpl" class="com.jbit.fsd.service.impl.UserServiceImpl">
    		<!-- 需要注意是是这里调用setDao()方法 -->
    		<property name="dao">
    			<ref local="userDao"></ref>
    		</property>
    	</bean>
    	
    	<bean id="userServiceImplByConstructor" class="com.jbit.fsd.service.impl.UserServiceImplByConstructor">
    		<!-- 通过定义的单参数构造为业务层的dao属性赋值 -->
    		<constructor-arg>
    			<!-- 引用id为userDao的对象为dao属性赋值 -->
    			<ref bean="userDao"/>
    		</constructor-arg>
    	</bean>
    </beans>
    

    上面的代码看:local属性和bean属性的用法和像,区别在于:当把spring的配置文件拆分为多个时,使用local属性只能在同一个配文件中检索Bean的id,而使用bean属性可以在其他配置文件中检索id。

    2.使用内部Bean

    	<bean id="userServiceImpl" class="com.jbit.fsd.service.impl.UserServiceImpl">
    		<!-- 需要注意是是这里调用setDao()方法 -->
    		<property name="dao" >
                         <bean class="com.pb.dao.impl.UserDaoimpl">
                     </property>  <!-- 属性注入 -->
    	</bean>
    

    如果属性中包含特殊字符如(&,<,>)等可将特殊字符替换为实体引用,如<替换为&It.

    3.注入集合类型的属性

    <?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:aop="http://www.springframework.org/schema/aop"
    		xmlns:tx="http://www.springframework.org/schema/tx"
    		xsi:schemaLocation="
    			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    		<!-- 以面向接口思想编程实现解耦和 -->
    	<bean id="userDao" class="com.jbit.fsd.dao.impl.UserDaoImpl">
    	</bean>
    	<bean id="user" class="com.pb.eneity.User">
    		<property name="hobbies">
    <!--list类型变量的注入 --> <list> <value>足球</value> <value>篮球</value> </list> </property> </bean> <bean id="user" class="com.pb.eneity.User"> <property name="hobbies">
    <!--ser类型变量的注入--> <set> <value>足球</value> <value>篮球</value> </set> </property> </bean> <bean id="user" class="com.pb.eneity.User"> <property name="hobbies">
                  <!-- map类型变量的注入 --> <map> <entry> <key><value>username</value></key> <ref bean="com.pb.entity.User"></ref> </entry> </map> </property> </bean> </beans>

    三、使用多种方式简化spring Ioc的配置

    1.使用p命名空间注入Bean属性

    使用p命名空间改进配置,改进前先添加p命名空间是声明。

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!--
      - Application context definition for JPetStore's business layer.
      - Contains bean references to the transaction manager and to the DAOs in
      - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation").
      -->
    <beans xmlns="http://www.springframework.org/schema/beans"
    		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    		xmlns:aop="http://www.springframework.org/schema/aop"
    		xmlns:tx="http://www.springframework.org/schema/tx"
    		xmlns:aop="http://www.springframework.org/schema/p"
    		xsi:schemaLocation="
    			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    	<bean id="userDao" class="com.jbit.fsd.dao.impl.UserDaoImpl" p:age="18" p:username="xiaoming">
    	</bean>
    </beans>
    

    使用p命名空间简化配对效果明显,使用语法总结:

    1.对于直接量(基本数据类型、字符串)属性,使用方式如下:

    p:属性名=“属性值”

    2.对于引用Bean的属性,使用方式如下:

    p:属性名-ref="Bean的id"

    2.Spring配置文件实现自动装配

    <bean>元素的autowire属性提供了一种自动注入的依赖对象的机制,配置Bean时不需要做任何显示的指定,spring会自动查找符合条件的依赖对象并实施注入。

    <bean id="userService"  class="com.pb.serviceImp.UserServiceImpl" autowire="byType">

    spring提供了几种自动装配的类型:

    1.no:默认值,Spring默认不进行自动装配,必须显示的指定依赖对象

    2.byName: 根据属性名自动装配,Spring自动查找与属性名相同的id,如果找到,则自动注入,否则什么也不做。

    3.byType:根据属性的类型自动装配,Spring自动查找与属性类型相同Bean,如果找到唯一的那个,则自动注入,如果找到多个与属性类型相同的Bean,则抛出异常,如果没找到则什么也不做。

    4.constructor:和byType类似,不过他针对构造方法,如果spring找到一个Bean和构造方法的参数类型像匹配,则通过构造方法注入到依赖对象,如果没有,则抛异常。

    如果每个Bean都设置autowire属性也是挺麻烦的,spring提供了default-autowire属性,设置全局的自动装配。

    <beans xmlns="http://www.springframework.org/schema/beans"
    		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    		xmlns:aop="http://www.springframework.org/schema/aop"
    		xmlns:tx="http://www.springframework.org/schema/tx"
    		xmlns:aop="http://www.springframework.org/schema/p"
    		xsi:schemaLocation="
    			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd" 
    			default-autowire="byType">
    

      

  • 相关阅读:
    Git常用命令
    更新CentOS内核
    VMware虚拟机安装Ubuntu系统步骤详解
    Ubuntu安装遇到的问题
    IOT OS and OTA
    gcc c asm,C程序内嵌汇编
    makefile and make tips
    RTEMS目录梳理Sparc
    关于FreeRTOS的信号量、队列
    FreeRTOS任务源码分析以及程序堆栈与任务堆栈的关系
  • 原文地址:https://www.cnblogs.com/ablejava/p/5657452.html
Copyright © 2011-2022 走看看