您的位置:首页 > 编程语言 > Java开发

Spring笔记(二):Ioc 之注入与装配

2015-01-16 22:49 204 查看
一、Spring依赖注入的原理

二、依赖注入的实现

(一)对象的注入

1、简单属性注入

1)源代码

package main.java.com.spring.ioc.base.dao.impl;

import main.java.com.spring.ioc.base.dao.PersonDao;

/**
*
* PersonDiDaoImpl
* @title
* @desc
* @author SAM-SHO
* @Dec 28, 2014
*/
public class PersonDiDaoImpl implements PersonDao {

@Override
public void save() {
System.out.println("PersonDiDaoImpl 的save()方法被调用了");

}

}


package main.java.com.spring.ioc.base.service.impl;

import main.java.com.spring.ioc.base.dao.PersonDao;
import main.java.com.spring.ioc.base.service.PersonService;

/**
* PersonDiServiceImpl
* @desc
* @author SAM-SHO
* @Dec 25, 2014
*/
public class PersonDiServiceImpl implements PersonService {

private PersonDao personDao;

@Override
public void save() {
personDao.save();
}

public PersonDao getPersonDao() {
return personDao;
}

public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}

}


2)配置文件

<!-- 1-依赖注入的实现 -->
<!-- 1-1 对象的注入 -->
<!-- 1-1-1 简单属性注入 -->

<bean id="PersonDiDaoImpl" class="main.java.com.spring.ioc.base.dao.impl.PersonDiDaoImpl"></bean>
<bean id="PersonDiService" class="main.java.com.spring.ioc.base.service.impl.PersonDiServiceImpl">
<property name="personDao" ref="PersonDiDaoImpl"></property><!-- 这边的name必须与类中setXXX()方法的XXX名字一致 -->
</bean>


3)测试

@Test
public void BeanDISucess() {

// 1- 对象的注入
// 1-1 简单属性注入 ref属性(推荐)
ApplicationContext cxt = new ClassPathXmlApplicationContext("application-di-Context.xml");
PersonService tPersonService = cxt.getBean("PersonDiService", PersonDiServiceImpl.class);//利用接口接收
tPersonService.save();//【输出】:PersonDiDaoImpl 的save()方法被调用了

}


4)分析:

①、使用关键元素 <property name="" ref="">

②、name:必须与类中setXXX()方法的XXX名字一致。即setPersonDao 与 与name="personDao"保持一致。

③、ref:指向定义好,需要注入的Bean 。

2、内部Bean注入

1)源代码

2)配置文件

<!-- 1-1-2 内部Bean属性注入 -->
<bean id="PersonDiService2" class="main.java.com.spring.ioc.base.service.impl.PersonDiServiceImpl">
<property name="personDao" >
<bean class="main.java.com.spring.ioc.base.dao.impl.PersonDiDaoImpl" />
</property>
</bean>


3)测试

// 1-2 使用内部Bean 的属性注入(注入的Bean 不能复用)
PersonService tPersonService2 = cxt.getBean("PersonDiService2", PersonDiServiceImpl.class);//利用接口接收
tPersonService2.save();//【输出】:PersonDiDaoImpl 的save()方法被调用了


4)分析:内部Bean注入,其实就是把需要注入的bean定义在 被注入的Bean 内部。其实这样反而达不到重复使用的效果。

(二)基本类型注入

1、String 的注入

1)源代码:在PersonDiServiceImpl 中增加属性 name 。修改save()方法

private String name;
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}


@Override
public void save() {
System.out.println("被注入的简单属性的值为:" + name);
personDao.save();
}


2)配置文件

<!-- 1-2  基本类型注入 -->
<bean id="personDiService3" class="main.java.com.spring.ioc.base.service.impl.PersonDiServiceImpl">
<property name="personDao" ref="PersonDiDaoImpl"></property>
<property name="name" value="SAM-SHO"></property>
</bean>


3)测试

// 2- 基本类型的注入
PersonService tPersonService3 = cxt.getBean("personDiService3", PersonDiServiceImpl.class);//利用接口接收
tPersonService3.save();//【输出】:被注入的简单属性的值为:SAM-SHO


2、Date 的注入

1)源代码:增加Date类型的属性并修改save()方法。

private Date date;
public Date getDate() {
return date;
}

public void setDate(Date date) {
this.date = date;
}
@Override
public void save() {
System.out.println("被注入的Date属性的值为:" + date);
System.out.println("被注入的简单属性的值为:" + name);
personDao.save();
}


2)配置文件:利用 SimpleDateFormat 的注入

<bean id="dateFormat" class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd" />
</bean>

<bean id="personDiService4" class="main.java.com.spring.ioc.base.service.impl.PersonDiServiceImpl">
<property name="personDao" ref="PersonDiDaoImpl"></property>
<property name="date" >
<bean factory-bean="dateFormat" factory-method="parse">
<constructor-arg value="2015-01-01" />
</bean>
</property>
</bean>


3)测试

// 2-2 Date类型的注入
PersonService tPersonService4 = cxt.getBean("personDiService4", PersonDiServiceImpl.class);//利用接口接收
tPersonService4.save();//【输出】:被注入的Date属性的值为:Thu Jan 01 00:00:00 CST 2015


4)分析:利用SimpleDateFormat 的parse()的实例工厂方法初始化其Bean,然后注入

(三)各种集合类型的注入

1、List集合类型

1)源代码:增加list属性

// List集合类型
private List<String> lists = new ArrayList<String>();
public List<String> getLists() {
return lists;
}

public void setLists(List<String> lists) {
this.lists = lists;
}


2)配置文件

<!-- 1-3  集合类型注入 -->
<bean id="personDiService5" class="main.java.com.spring.ioc.base.service.impl.PersonDiServiceImpl">
<property name="personDao" ref="PersonDiDaoImpl"></property>
<!--1-3-1 List集合的注入-->
<property name="lists">
<list>
<value>第1个List值</value>
<value>第2个List值</value>
<value>第3个List值</value>
</list>
</property>

</bean>


3)测试

// 3-集合类型的注入
PersonDiServiceImpl tPersonDiService5 = cxt.getBean("personDiService5", PersonDiServiceImpl.class);

// 3-1 List 集合的注入
for (String strValue : tPersonDiService5.getLists()) {
System.out.println("List 集合注入的值: " + strValue);
}

System.out.println("--------------------------");


4)分析:使用<list> 标签

2、Set集合类型

1)源代码

// Set集合类型
private Set<String> sets = new HashSet<String>();
public Set<String> getSets() {
return sets;
}

public void setSets(Set<String> sets) {
this.sets = sets;
}


2)配置文件

<!--1-3-2 Set 集合的注入-->
<property name="sets">
<set>
<value>第yi个set值</value>
<value>第er个set值</value>
<value>第san个set值</value>
</set>
</property>


3)测试

PersonDiServiceImpl tPersonDiService5 = cxt.getBean("personDiService5", PersonDiServiceImpl.class);
//3-2 set集合的注入
for (String strValue : tPersonDiService5.getSets()) {
System.out.println("Set集合注入的值: " + strValue);
}


4)分析:<set> 标签

3、Properties 集合类型

1)源代码

// Properties 集合类型
private Properties properties = new Properties();
public Properties getProperties() {
return properties;
}

public void setProperties(Properties properties) {
this.properties = properties;
}


2)配置文件

<!--1-3-3 Properties 集合的注入-->
<property name="properties">
<props>
<prop key="key1">1-properties-Value</prop>
<prop key="key2">2-properties-Value</prop>
<prop key="key3">3-properties-Value</prop>
</props>
</property>


3)测试

ApplicationContext cxt = new ClassPathXmlApplicationContext("application-di-Context.xml");
PersonDiServiceImpl tPersonDiService5 = cxt.getBean("personDiService5", PersonDiServiceImpl.class);
// 3-3 Properties 集合的注入
for (Object key : tPersonDiService5.getProperties().keySet()) {
System.out.println("Properties 集合注入的值: " + tPersonDiService5.getProperties().get(key));
}


4)分析:<props><prop key="key1">1-properties-Value</prop></props>

4、Map 集合类型

1)源代码

// Map 集合类型
private Map<String,String> maps = new HashMap<String,String>();
public Map<String, String> getMaps() {
return maps;
}

public void setMaps(Map<String, String> maps) {
this.maps = maps;
}


2)配置文件

<!--1-3-4 Map集合的注入  -->
<property name="maps">
<map>
<entry key="key1" value="mapValue1"></entry>
<entry key="key2" value="mapValue2"></entry>
<entry key="key3" value="mapValue3"></entry>
</map>
</property>


3)测试

// 3-4 Map 集合的注入(其实Map 也可以利用 Properties 的配置实现)
for (String key : tPersonDiService5.getMaps().keySet()) {
System.out.println("Map 集合注入的值: " + tPersonDiService5.getMaps().get(key));
}


4)分析:<map><entry key="key1" value="mapValue1"></entry></map>

三、依赖注入的方式

1、属性注入:即一个对象作为属性存在于另一个对象中,有 setter 和 getter 方法。

1)源代码
private PersonDao personDao;
public PersonDao getPersonDao() {
return personDao;
}

public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}


2)配置文件
<bean id="PersonDiDaoImpl" class="main.java.com.spring.ioc.base.dao.impl.PersonDiDaoImpl"></bean>
<bean id="PersonDiService" class="main.java.com.spring.ioc.base.service.impl.PersonDiServiceImpl">
<property name="personDao" ref="PersonDiDaoImpl"></property><!-- 这边的name必须与类中setXXX()方法的XXX名字一致 -->
</bean>


2、构造器注入

1)源代码

// 一定要有无参的构造方法
public PersonDiServiceImpl() {

}

// 构造器注入
public PersonDiServiceImpl(PersonDao personDao, String name) {
this.personDao = personDao;
this.name = name;
}


2)配置文件

<bean id="personDao" class="main.java.com.spring.ioc.base.dao.impl.PersonDiDaoImpl"></bean>
<!-- 2-2 构造器注入 -->
<bean id="personDiService7" class="main.java.com.spring.ioc.base.service.impl.PersonDiServiceImpl">
<constructor-arg index="0" ref="personDao" ></constructor-arg>
<constructor-arg index="1" type="String" value="构造器注入" ></constructor-arg>
</bean>


3)测试

// 2-构造器注入 constructor-arg

// 一定要有无参的构造方法
ApplicationContext cxt = new ClassPathXmlApplicationContext("application-di-Context.xml");
PersonService tPersonService = cxt.getBean("personDiService7", PersonDiServiceImpl.class);//利用接口接收
tPersonService.save();


【输出】
// 被注入的简单属性的值为:构造器注入
// PersonDiDaoImpl 的save()方法被调用了


4)分析

①、<constructor-arg>标签。

②、一定要有无参的构造方法

3、使用Field注入(用于注解方式)

1)java 的@Resource(推荐)

2)spring 的@Autowire

四、注解完成Bean的注入

(一)Resource注解

1、剖析@Resource注解的实现原理

2、实现

1)源代码

	@Resource
private PersonDao personDao; public PersonDao getPersonDao() { return personDao; } public void setPersonDao(PersonDao personDao) { this.personDao = personDao; }


2)配置文件

<!-- 1-注解方式注入  -->
<!-- 1-支持注解 -->
<context:annotation-config/>

<!-- 2-定义两个Bean -->
<bean id="personDao" class="main.java.com.spring.ioc.base.dao.impl.PersonDiDaoImplAnnocation"></bean>
<bean id="personServiceImplAnnotation" class="main.java.com.spring.ioc.base.service.impl.PersonDIServiceImplAnnotation"></bean>


3)测试

ApplicationContext cxt = new ClassPathXmlApplicationContext("application-di-annotation-Context.xml");
PersonService tPersonService = cxt.getBean("personServiceImplAnnotation", PersonDIServiceImplAnnotation.class);//利用接口接收
tPersonService.save();//【输出】PersonDiDaoImplAnnocation 的save()方法被调用了


3、分析

1)需要增加context的xml_Schema 和 <context:annotation-config/>。这个配置这个配置隐式注册了多个对注解进行解析处理的处理器 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor。

2)@Resource 注解需要导入common-annotations.jar。默认按名称装配,如果没有指定了name属性,则找不到就会按类型。

3)两个注解可以放在属性或者setXXX方法上。

(二)@Autowire 注解

1、实现

1)源码

//默认情况下要求依赖对象必须存在,如果允许为null,可以设置它required=false
//	@Autowired(required=true)
//	@Autowired@Qualifier("personDao")
@Autowired
private PersonDao personDao;


2、分析

1)@Autowired 默认按类型装配。想使用名称装配可以结合 @Qualifier("personDao") 使用。

3、默认情况下要求依赖对象必须存在,如果允许为null,可以设置它required=false 。

五、自动装配(不推荐)

(一)自动装配

1、xml配置:Autowired

1)byType: 按属性类型装配,多个匹配的Bean类型,抛异常

2)byName:按属性名称装配

3)constructor:构造器参数类型

4)autodetect:通过自省机制,自动决定。有默认构造器,则按byType 。

(二)实例

1、配置

<!-- 2-自动装配 -->
<bean id="personDao1" class="main.java.com.spring.ioc.base.dao.impl.PersonDiDaoImplAnnocation"></bean>
<bean id="personServiceImplAnnotation1" autowire="byName" class="main.java.com.spring.ioc.base.service.impl.PersonDIServiceImplAnnotation"></bean>


2、测试

/*
* 自动装配
* xml配置:Autowired :
* 1、byType: 按属性类型装配,多个匹配的Bean类型,抛异常
* 2、byName:按属性名称装配
* 3、constructor:构造器参数类型
* 4、autodetect:通过自省机制,自动决定。有默认构造器,则按byType 。
*/
PersonService tPersonService = cxt.getBean("personServiceImplAnnotation1", PersonDIServiceImplAnnotation.class);//利用接口接收
tPersonService.save();//【输出】PersonDiDaoImplAnnocation 的save()方法被调用了


六、Spring自动扫描和管理Bean

(一)自动扫描:用注解管理Bean

1、四个注解:

1)@Controller:最常见用于action,配以@Scope("prototype")。

2)@Service:用于service层。

3)@Repository:用于Dao层。

4)@Component:用于不同于上者三个注解。

2、配置需要扫描的包

<!-- 3-自动扫描 -->
<context:component-scan base-package="main.java.com.spring.*"></context:component-scan>


3、@PostConstruct:对应init-method 方法,在构造方法之后。

4、@PreDestroy:destroy-method 方法,容器关闭之前。

(二)自动扫描与注解结合

1、源码:

@Service
public class PersonDIServiceImplAnnotation implements PersonService {

@Resource
private PersonDao personDao;
}


@Repository
public class PersonDiDaoImplAnnocation implements PersonDao {

@Override
public void save() {
System.out.println("PersonDiDaoImplAnnocation 的save()方法被调用了");

}

}


2、配置:

<context:annotation-config/>
<context:component-scan base-package="main.java.com.spring.*"></context:component-scan>


1)不需要使用任何Bean的配置。

2)甚者,在使用自动扫描的配置下,可以省略解析注解的配置。因为配置注解只是隐式注册了多个对注解进行解析处理的处理器 ,而自动扫描可以起到一样的效果。

<context:component-scan base-package="main.java.com.spring.*"></context:component-scan>


3、测试

//自动扫描
@Test
public void beanAutoScrean(){

AbstractApplicationContext cxt = new ClassPathXmlApplicationContext("application-di-annotation-Context.xml");
PersonService tPersonService = cxt.getBean("personDIServiceImplAnnotation", PersonDIServiceImplAnnotation.class);//利用接口接收
//		tPersonService.save();
tPersonService.save();
cxt.close();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: