Spring IOC丶依赖注入

1. Spring IOC

1.1 概述

  • 把实体的创建权交给Spring,以便解耦,Spring使用配置文件+实例工厂+反射创建实例

1.2 配置文件applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans 
	xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- id:实例的名称,可以被配置文件和Spring创建实例时引用 -->
	<!-- class:被实例化的类完整路径 -->
	<!-- scope:实例的作用范围
			singleton:单例,该类只会创建一次对象,默认值(常用)
			prototype:多例,每次从容器中获取Bean时,都会创建一个新的实例,Acition实例化需要多例(常用)
			request:用于Web应用环境,针对每次HTTP请求都会创建一个实例
			session:用于Web应用环境,同一个会话共享同一个实例,不同的会话使用不同的实例
			global session:仅在Portlet的Web应用中使用,同一个全局会话共享一个实例,对于非Portlet环境,等同于session
	-->
	<bean id="student" class="com.domain.Student" scope="singleton"></bean>	

<!-- 在一个配置文件中引入多个配置文件(配置文件拆分) -->
<import resource="/applicationContext2.xml"/>	
</beans>

1.3 从Spring容器中获取实例

//读取spring配置文件
ApplicationContext ac=new ClassPathXmlApplicationContext("/applicationContext.xml");
//根据bean标签的id属性值查找实例
Student student= ac.getBean("student",Student.class);
//操作实例对象
System.out.println(student.toString());

2. 依赖注入

2.1 构造方法注入属性值

<bean id="student" class="com.domain.Student">
	<!-- Student类中定义了构造方法Student(Integer id, String name) -->
	<!-- constructor-arg表示构造方法的参数,name表示参数名称,value表示参数值 -->
	<constructor-arg name="id" value="1"></constructor-arg>
	<constructor-arg name="name" value="张三"></constructor-arg>
</bean>

2.2 setter方法注入属性值

<bean id="grade" class="com.domain.Grade">
	<!-- property标签表示一个属性,name表示属性名,value表示要注入的属性值 -->
	<property name="id" value="1"></property>
	<property name="name" value="高一(1)班"></property>
</bean>

<bean id="student" class="com.domain.Student">
	<!-- ref可以注入对象类型的数据,ref的值对应上面id为grade的bean -->		
	<property name="grade" ref="grade"></property>
</bean>

2.3 p命名空间注入属性值

  • Spring2.5后才能使用p命名空间
  • 需要在beans标签下引入p命名空间规范
    xmlns:p="http://www.springframework.org/schema/p"
<!-- 直接在bean标签的属性中使用p命名空间为对的属性赋值 -->
   <!-- 基本类型格式:【p:对象属性名="值"】 -->
   <!-- 对象引用格式:【P:对象属性名-ref="值"】 --> 
<bean id="grade" class="com.domain.Grade" p:id="2" p:name="高一(4)班"></bean>
<bean id="student" class="com.domain.Student" p:grade-ref="grade"></bean>

2.4 SpEL注入属性值

  • Spring3后才能使用SpEL
  • SpEL能执行java代码(跟EL表达式类似)
<bean id="grade" class="com.domain.Grade">
	<!-- SpEL表达式格式:   #{值}    值为字符串需要加单引号 -->		
	<property name="id" value="#{3}"></property>
	<property name="name" value="#{'高三(3)班'}"></property>
</bean>

<bean id="student" class="com.domain.Student">	
	<!-- 无论值是否为对象类型,直接用value即可,SpEL会自动解析值类型 -->		
	<property name="grade" value="#{grade}"></property>
	<!-- SpEL可以执行java代码 -->
	<property name="name" value="#{grade.getName()+'的学生'}"></property>
</bean>

2.5 自动装配autowire

  • 2.5.1 自动装配autowire属性值
    • byName

      • 根据属性名自动装配,
      • BeanFactory查找id与属性的setter方法匹配的Bean,找到即自动注入,否则什么都不做
    • byType 根据属性类型自动装配

      • 如果正好有一个与依赖属性类型相同的Bean,就自动装配这个属性
      • 如果有多个这样的的Bean,Spring无法决定哪个Bean,就抛出一个致命异常
      • 如果没有匹配的Bean,就什么都不做,属性不会被设置
    • no

      • 不使用自动装配
    • constructor

      • 跟byType差不多,它是应用于构造注入自动装配
      • 如果在容器中没有找到与构造器参数类型一致的Bean,那么将会抛出异常
<bean id="userDao" class="com.dao.impl.UserDaoImpl" ></bean>	
<bean id="productDao" class="com.dao.impl.ProductDaoImpl"></bean>

<!-- ShoppingCarServiceImpl中需要用到userDao和productDao,autowire能自动给这两个属性值(需要setter方法)自动装配赋值 -->
<bean id="shoppingCarService" class="com.service.impl.ShoppingCarServiceImpl" autowire="byName"></bean>
  • 全局自动装配
    • Spring配置文件设置了default-autowire后当前文件的bean都会默认自动装配,如果是拆分多个配置文件,只有设置了default-autowire的配置文件才生效,其他配置文件不生效
 <!-- 在Spring配置文件开头的<beans>文件中添加default-autowire="自动装配值" -->
<beans default-autowire="byName" >

2.6 注入不同类型的数据(了解)

  • 注入基本类型(字符串和其他基本类型)

    • 看上面例子
  • 引用bean实例

    • 看上面例子
  • 使用内部Bean

<bean id="userBiz" class="com.biz.impl.UserBizImpl">
	 <property name="userDao">
	     <!-- 内部bean直接使用class属性,不用id属性,不能被其他bean调用 -->
	     <bean class="com.dao.impl.UserDaoImpl"></bean>
	 </property>
</bean>
  • 注入List集合或数组类型的属性值
<bean id="user" class="com.entity.User">
	  <property name="hobbies">
	      <!-- list标签注入List集合或数组的多个值 -->
	      <list>
	          <value>篮球</value>
	          <value>足球</value>
	          <value>乒乓球</value>
	      </list>
	  </property>
</bean>
  • 注入Set集合的属性值
<bean id="user" class="com.entity.User">
	<property name="hobbies">
	    <!-- set标签注入Set集合 -->
	    <set>
	        <value>篮球</value>
	        <value>足球</value>
	        <value>乒乓球</value>
	    </set>
	</property>
</bean>
  • 注入Map集合的属性值
<bean id="user" class="com.entity.User">
   <property name="hobbies">
        <!-- map标签注入Map集合多个键值对 -->
        <map>
            <!-- 一个entry标签表示一个键值对 -->
            <entry>
                <!-- entry标签的子key标签表示Map集合的key,key标签包含的value表示key值 -->
                <key><value>basketball</value></key>
                <!-- entry标签的子value标签表示Map集合的value -->
                <value>篮球</value>
            </entry>
            <entry>
                <key><value>football</value></key>
                <value>足球</value>
            </entry>
        </map>
    </property>
</bean>
  • 注入Properties类型的属性值
<bean id="user" class="com.entity.User">
	<property name="hobbies">
	    <!-- props标签注入Properties集合多个键值对 -->
	    <props>
	        <!-- 一个prop标签表示一个键值对 -->
	        <!-- key属性表示key值 -->
	        <!-- prop标签包含的文本是value值 -->
	        <prop key="backetball">篮球</prop>
	        <prop key="football">足球</prop>
	    </props>
	</property>
</bean>
  • 注入null和空字符串值
<!-- value标签中间不填东西就是空字符串 -->
<property name="a"><value></value></property>
<!-- null标签表示null值 -->
<property name="b"><null/></property>

3. 使用注解方式依赖注入

3.1 修改配置文件

  • 标签多了个xmlns:context项,xsi:schemaLocation的值多了2个
  • 设置扫描注解类的包
  • default-autowire设置和context:component-scan是在同一个配置文件,则会对类的对象属性进行自动装配(对象属性需要要setter方法,不需要在对象属性上添加注解)
<?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:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">

	
	<!-- 注解组件扫描,base-package表示要扫描的包,多个包用逗号隔开 -->
	<context:component-scan base-package="com.service.impl,com.dao.impl"></context:component-scan>
</beans>

3.2 常用注解

  • 3.2.1 注解定义bean
    • @Repository("bean id") 用于标注Dao的实现类
@Repository("productDao")
public class ProductDaoImpl implements ProductDao {}
  • @Service("bean id") 用于标注Service实现类
@Service("shoppingCarService")
public class ShoppingCarServiceImpl implements ShoppingCarService {}
  • @Controller("bean id") 用于标注控制器类
  • @Component("bean id") 用于标注通用bean的类
  • 3.2.2 自动装配注解
    • 注解自动装配不用setter方法,直接在属性上面添加注解即可
    • @Autowired 根据类型进行自动装配
    • @Qualifier("bean id") 与@Autowired结合一起使用就变成根据名字进行自动装配
    • @Resource(name="bean id") 根据名字进行自动装配,等同于上面两个结合
//@Autowired与@Qualifier结合一起就是按名字自动装配
@Autowired 
@Qualifier("userDao")
private UserDao userDao;

//根据名字进行自动装配
@Resource(name="productDao")
private ProductDao productDao;
  • 3.2.3 基本类型数据注解
@Value("我是注解方式的属性值")
private String message;
  • 3.2.4 bean作用域注解
    @Scope("作用域") 在类上面注解作用范围,作用域的值参考2.5
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章