4、IOC和DI

4.1、IOC容器

4.1.1、ObjectFactory 和ApplicationContext

BeanFactory:这个接口是spring中最底层的接口,只提供了最简单的IoC功能(创建bean,获取bean,销毁bean)

在一般的应用当中,一般不使用BeanFactory;推荐用ApplicationContext(应用上下文);

1.ApplicationContext继承了BeanFactory,提供了基本的IoC功能;

2.ApplicationContext还提供了其他功能,比如支持国际化,消息机制,统一的资源加载,AOP功能等

4.1.2、ApplicationContext的实现类

1、ClassPathXmlApplicationContext:读取classpath中的资源

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

2、FileSystemXmlApplicationContext

ApplicationContext ac = new FileSystemXmlApplicationContext("c:/licationContext.xml");

3、XmlWebApplicationContext

XmlWebApplicationContext ac = new XmlWebApplicationContext();
// 需要指定ServletContext对象
ac.setServletContext(servletContext);
// 指定配置文件路径,开头的斜线表示Web应用的根目录
ac.setConfigLocation("/WEB-INF/applicationContext.xml"); 
// 初始化容器
ac.refresh(); 

4.1.3、Resource常用实现类

ClassPathResource:从classpath根路径开始找配置文件

FileSystemResource:从磁盘的文件路径去找c://xx.xml

ServletContextResource:应用于web中,从web中去找配置文件

4.2、Bean的创建时机

1.ApplicationContext在加载的时候就会创建所有的bean(Web应用建议)

2.BeanFactory需要等到拿bean的时候才会创建bean(延迟加载)(桌面程序)

延迟加载

ApplicationContext做到延迟加载的效果:
针对于当前xml中所有的bean。

<beans default-lazy-init="default | false | true">

针对于指定的bean:

<beans lazy-init="default | false | true">

4.3、Bean的作用域

<bean id="" class="" scope="作用域"/>

singleton: 单例 :在Spring IoC容器中仅存在一个Bean实例 (默认的scope)

prototype: 多例 :每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时 ,相当于执行new 不会在容器启动时创建对象

对于MVC中的Action(Struts2)使用prototype类型,其他使用singleton

4.4、初始化和销毁方法

<bean id="someBean" class="......" 
   		init-method="该类中初始化方法名" destroy-method="该类中销毁方法名">
</bean>

init-method:bean生命周期初始化方法,对象创建后就进行调用

destroy-method:容器被销毁的时候,如果bean被容器管理,会调用该方法。

如果bean的scope="prototype",那么容器只负责创建和初始化,它并不会被spring容器管理。

4.5、Bean的实例化的方式

4.5.1、构造器

构造器实例化,最标准,使用最多

java类

public class SomeBean1 {}

xml配置

<bean id="someBean1" class="SomeBean1全限定名"/>

4.5.2、静态工厂方式

java类

public class SomeBean2Factory {
	public static SomeBean2 getSomeBean2(){
		return new SomeBean2();
	}
}
public class SomeBean2 {}

xml配置

<bean id="someBean2" class="SomeBean2Factory全限定名" factory-method="getSomeBean2"/>

此时我们通过上下文对象获取id为someBean2的对象,这个对象的类型为SomeBean2

4.5.3、实例工厂方式

实例工厂方法实例化:解决系统遗留问题,有点麻烦,使用比较少

public class SomeBean3 {}
public class SomeBean3Factory {
	public SomeBean3 getSomeBean3() {
		return new SomeBean3();
	}
}

xml配置

<bean id="someBean3Factory" class="SomeBean3Factory全限定名"/>
<bean id="someBean3" factory-bean="someBean3Factory" factory-method="getSomeBean3"/>

此时我们获取id为someBean3的对象,实际上会创建实例工厂,然后在通过实例工厂的工厂方法来或者SomeBean3的对象

4.5.4、实现FactoryBean接口实例化

java类

public class SomeBean4 {}
public class SomeBean4FactoryBean implements FactoryBean<SomeBean4>{
     //返回对象
	public SomeBean4 getObject() throws Exception {
		return new SomeBean4();
	}
     //返回对象的类型
	public Class<?> getObjectType() {
		return SomeBean4.class;
	}
     //返回是否单例
	public boolean isSingleton() {
		return true;
	}
}

xml配置

<bean id="someBean4" class="SomeBean4FactoryBean全限定名" />

4.6、DI和ioc介绍

IoC(inverse of control):指将对象的创建权,反转到Spring容器;

DI (Dependency Injection) :指Spring创建对象的过程中,将对象依赖属性通过配置进行注入 。

其实它们是同一个概念的不同角度描述。DI相对IoC而言,明确描述了”被注入对象依赖IoC容器配置依赖对象”。

4.6.1、注入方式

使用setter注入:

1.使用bean元素的property子元素设置;

​ 简单类型值,直接使用value赋值;

​ 引用类型,使用ref赋值;

​ 集合类型,直接使用对应的集合类型元素即可。

2.spring通过属性的setter方法注入值;

3.在配置文件中配置的值都是string,spring可以自动的完成类型的转换

4.属性的设置值是在init方法执行之前完成的

构造器注入

1.spring在实例化对象的时候,如果对象没有配置constructor-arg,则使用默认的构造器实例化对象

2.如果有constructor-arg,那么spring使用这些constructor-arg来唯一确定一个构造器

4.6.2、注入值的类型

1、简单类型数据

java类编写

public class Employee {
	private String name;
	private Integer age;
	private Double salary;
	private URL url;
       省略setter/getter
}

xml配置

<bean id="emp" class = "com.luke.pojo.Employee">
        <property name="name" value="kingdom" />
        <property name="age" value="17" />
        <property name="salary" value="123" />
        <property name="url" value="http://urlValue" />
</bean>

2.对象类型的值

java类

public class EmpDAO {
	public void save(){
		System.out.println("EmpDAO.save()");
	}
}
public class EmpService {
	private EmpDAO dao;//持有一个引用数据类型

	public void setDao(EmpDAO dao) {
		this.dao = dao;
	}

	public void save() {
		dao.save();
		System.out.println("EmpService.save()");
	}
}

xml文件配置

<bean id="empDAO" class="com.luke.dao.EmpDAO" />
<bean id="empService" class="com.luke.service.EmpService">
		<property name="dao" ref="empDAO" />
</bean>

3.注入集合类型

java类

public class ConnectionBean {
	private Set<String> set;
	private List<String> list;
	private String[] array;
	private Map<String, String> map;
	private Properties prop;
       省略setter/getter
}

xml文件配置

<bean id="collectionBean" class="com.luke.dbc.ConnectionBean">
		<property name="set">
			<set>
				<value>set1</value>
				<value>set2</value>
				<value>set3</value>
			</set>
		</property>
		<property name="list">
			<list>
				<value>list1</value>
				<value>list2</value>
				<value>list3</value>
			</list>
		</property>
		<property name="array">
			<list>
				<value>array1</value>
				<value>array2</value>
				<value>array3</value>
			</list>
		</property>
		<property name="map">
			<map>
				<entry key="key1" value="value1"/>
				<entry key="key2" value="value2"/>
				<entry key="key3" value="value3"/>
			</map>
		</property>
		<property name="prop">
			<props>
				<prop key="pKey1">pVal1</prop>
				<prop key="pKey2">pVal2</prop>
				<prop key="pKey3">pVal3</prop>
			</props>
		</property>
	</bean>

4.7、属性占位符

1、maven依赖

 <!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
<dependency>
    <groupId>commons-dbcp</groupId>
    <artifactId>commons-dbcp</artifactId>
    <version>1.4</version>
</dependency>

        <!-- https://mvnrepository.com/artifact/com.oracle.jdbc/com.springsource.oracle.jdbc -->
<dependency>
    <groupId>com.oracle.jdbc</groupId>
    <artifactId>com.springsource.oracle.jdbc</artifactId>
    <version>10.2.0.2</version>
</dependency>

2、引入context命名空间

<?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
        ">
</beans>

3、拷贝db.properties文件

db.driver=oracle.jdbc.driver.OracleDriver
db.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
db.username=scott
db.password=tiger

4、加载配置文件

<context:property-placeholder location="classpath:db.properties"/>
<bean id = "ds" class="org.apache.commons.dbcp.BasicDataSource">
   		<property name="driverClassName" value="${db.driver}"></property>
   		<property name="url" value="${db.url}"></property>
   		<property name="username" value="${db.username}"></property>
   		<property name="password" value="${db.password}"></property>
</bean>

5、测试

package com.luke.test;
import com.luke.pojo.Employee;
import com.luke.pojo.Hello;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.sql.DataSource;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
//表示先启动Spring容器,把junit运行在Spring容器中
@RunWith(SpringJUnit4ClassRunner.class)
//表示从哪里加载资源文件
@ContextConfiguration("classpath:applicationContext.xml")
public class TestHello {
    //自动加载
    @Autowired
    BeanFactory beanFactory ;
    @Test
    public void testConnect(){
        DataSource ds = beanFactory.getBean("ds", DataSource.class);
        try {
            System.out.println(ds.getConnection());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

posted @ 2021-04-08 15:08  Mirindasky  阅读(45)  评论(0编辑  收藏  举报