1. 简介
IOC-全称Inversion of Control,中文解释:控制反转。另外,IOC又称DI(全称)Dependency Injection,中文解释:依靠注入。
2. 注入类型
a)setter(重要)
b)构造方法(可以忘记)
c)接口注入(可以忘记)
3. id vs. namea)name可以用特殊字符
4.简单属性的注入
a)<property name=… value=…>
5.<bean 中的scope属性
a)singleton 单例b)proptotype 每次创建新的对象
6.集合注入
a)很少用,不重要!参考程序
7.自动装配
a)byName
b)byType
c)如果所有的bean都用同一种,可以使用beans的属性:default-autowire
8.生命周期
a)lazy-init (不重要)
b)init-method destroy-methd 不要和prototype一起用(了解)
9.Annotation第一步:
a)修改xml文件,参考文档<context:annotation-config />
10.@Autowired
a)默认按类型by type
b)如果想用byName,使用@Qulifier
c)写在private field(第三种注入形式)(不建议,破坏封装)
d)如果写在set上,@qualifier需要写在参数上
11.@Resource(重要)
a)加入:j2ee/common-annotations.jar
b)默认按名称,名称找不到,按类型
c)可以指定特定名称
d)推荐使用
e)不足:如果没有源码,就无法运用annotation,只能使用xml
12.@Component @Service @Controller @Repository
a)初始化的名字默认为类名首字母小写
b)可以指定初始化bean的名字
以下是详细测试代码,部分代码已经被注释,方便测试
xml测试:
1、model
package dhp.model;
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2、dao
package dhp.dao;
import dhp.model.User;
public interface UserDao {
public void save(User user);
}
3、daoimpl
package dhp.dao.impl;
import java.util.List;
import java.util.Map;
import java.util.Set;
import dhp.dao.UserDao;
import dhp.model.User;
public class UserDaoImpl implements UserDao {
private int daoId;
//private String daoStatus;
public int getDaoId() {
return daoId;
}
public void setDaoId(int daoId) {
this.daoId = daoId;
}
/*public String getDaoStatus() {
return daoStatus;
}
public void setDaoStatus(String daoStatus) {
this.daoStatus = daoStatus;
}
*/
private Set<String> sets;
private List<String> lists;
private Map<String, String> maps;
public Set<String> getSets() {
return sets;
}
public void setSets(Set<String> sets) {
this.sets = sets;
}
public List<String> getLists() {
return lists;
}
public void setLists(List<String> lists) {
this.lists = lists;
}
public Map<String, String> getMaps() {
return maps;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
@Override
public void save(User user) {
System.out.println("user saved!");
//System.out.println("daoId:==="+daoId+"daoStatus:==="+daoStatus);
}
@Override
public String toString() {
/*return "sets size:" + sets.size() + "| lists size:" + lists.size() +
"| maps size:" + maps.size();*/
return "daoId:"+daoId;
}
}
4、service
package dhp.service;
import dhp.dao.UserDao;
import dhp.model.User;
public class UserService {
private UserDao userDao;
//构造方法注入
/*public UserService(UserDao userDao) {
super();
this.userDao = userDao;
}*/
public void init(){
System.out.println("=========init");
}
public void add(User user){
userDao.save(user);
}
public UserDao getUserDao() {
return userDao;
}
//set方式注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void destroy(){
System.out.println("==========destroy");
}
}
5、test
package dhp.service;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import dhp.dao.UserDao;
import dhp.model.User;
public class UserServiceTest {
@Test
public void testAdd() {
//ClassPathXmlApplicationContext继承自ApplicationContext,而ApplicationContext继承自BeanFactory
//推荐使用
//创建IOC容器
ClassPathXmlApplicationContext ctx =new ClassPathXmlApplicationContext("beans.xml");
//从IOC容器中得到bean的对象实例
UserService userService = (UserService) ctx.getBean("userService");
//UserService userService2 = (UserService) ctx.getBean("userService");
//System.out.print("验证singleton和prototype:");
//System.out.println(userService==userService2);//为 true,说明我们取出的是同一个对象
ctx.destroy(); //destroy必须手动指定,因为web环境下会自动destroy,必须是ClassPathXmlApplicationContext,不会监控prototype,只会监控singleton
/*BeanFactory applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) applicationContext.getBean("userService");*/
User user = new User();
user.setUsername("dhp");
user.setPassword("123456");
userService.add(user);
//测试collection
/*UserDao userDao = (UserDao) ctx.getBean("userDao");
System.out.println(userDao);*/
//测试byName和byType
System.out.println("=========="+userService.getUserDao());
}
}
6、beans.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"
>
<!-- 放在beans里面 -->
<!-- default-lazy-init="default"全局不启动 -->
<!-- default-autowire="default" 全局的自动注入-->
<bean id="userDao" class="dhp.dao.impl.UserDaoImpl"><!-- id也可以写出name, 只不过name是可以支持特殊字符的 -->
<!-- 简单属性注入,很少使用 -->
<!-- <property name="daoId" value="10"></property>
<property name="daoStatus" value="working"></property> -->
<!-- 集合 -->
<!--<property name="sets"> 相当于调用了setSets(Set<String> sets)
<set>
<value>1</value>
<value>2</value>
</set>
</property>
<property name="lists">相当于调用了setLists(List<String> lists)
<list>
<value>A</value>
<value>B</value>
<value>C</value>
</list>
</property>
<property name="maps"> 相当于调用了setMaps(Map<String, String> maps)
<map>
<entry key="1" value="map1"></entry>
<entry key="2" value="map2"></entry>
<entry key="3" value="map3"></entry>
<entry key="4" value="map4"></entry>
</map>
</property> -->
<!-- <property name="">
<props>
<prop key="">...</prop>
<prop key="">...</prop>
<prop key="">...</prop>
</props>
</property> -->
<property name="daoId" value="100"></property>
</bean>
<bean id="userDao2" class="dhp.dao.impl.UserDaoImpl" lazy-init="true"><!--设为true, new 的时候不启动 -->
<property name="daoId" value="200"></property>
</bean>
<!-- 自动注入时,不能有构造方法 -->
<!-- byName要求必须id和service里的属性一致 -->
<!-- byName:在容器中寻找和需要自动装配的属性名相同的Bean(或ID),如果没有找到相符的Bean,该属性就没有被装配上。 -->
<!-- byType:在容器中寻找一个与需要自动装配的属性类型相同的Bean;
如果没有找到相符的Bean,该属性就没有被装配上,如果找到超过一个相符的Bean抛出异常 -->
<!-- constructor 与byType方式类似,不同之处在于它应用于构造器参数。
如果容器中没有找到与构造器参数类型一致的bean,
那么抛出异常。 -->
<!-- default: <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"
default-autowire="default">
-->
<!-- scope默认是 singleton -->
<bean id="userService" class="dhp.service.UserService" scope="singleton" autowire="byName" init-method="init" destroy-method="destroy">
<!-- 方式1.1 -->
<!-- <property name="userDao" ref="userDao"></property> -->
<!-- 方式1.2 -->
<!-- <property name="userDao">
<ref bean="userDao"/>
</property> -->
<!-- 方式2 -->
<!-- <constructor-arg>
<ref bean="userDao"/>
</constructor-arg> -->
</bean>
</beans>
注解测试:
1、daoimpl
package dhp.dao.impl;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.stereotype.Component;
import dhp.dao.UserDao;
import dhp.model.User;
@Component("userDaoImpl")
public class UserDaoImpl implements UserDao {
private int daoId;
//private String daoStatus;
public int getDaoId() {
return daoId;
}
public void setDaoId(int daoId) {
this.daoId = daoId;
}
/*public String getDaoStatus() {
return daoStatus;
}
public void setDaoStatus(String daoStatus) {
this.daoStatus = daoStatus;
}
*/
private Set<String> sets;
private List<String> lists;
private Map<String, String> maps;
public Set<String> getSets() {
return sets;
}
public void setSets(Set<String> sets) {
this.sets = sets;
}
public List<String> getLists() {
return lists;
}
public void setLists(List<String> lists) {
this.lists = lists;
}
public Map<String, String> getMaps() {
return maps;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
@Override
public void save(User user) {
System.out.println("user saved!");
//System.out.println("daoId:==="+daoId+"daoStatus:==="+daoStatus);
}
@Override
public String toString() {
/*return "sets size:" + sets.size() + "| lists size:" + lists.size() +
"| maps size:" + maps.size();*/
return "daoId:"+daoId;
}
}
2、service
package dhp.service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import dhp.dao.UserDao;
import dhp.model.User;
@Component("userService")
public class UserService {
private UserDao userDao;
//构造方法注入
/*public UserService(UserDao userDao) {
super();
this.userDao = userDao;
}*/
@PostConstruct
public void init(){
System.out.println("=========init");
}
public void add(User user){
userDao.save(user);
}
public UserDao getUserDao() {
return userDao;
}
//set方式注入
/*@Autowired//默认通过byType
public void setUserDao(@Qualifier("userDao2") UserDao userDao) {
this.userDao = userDao;
}*/
//@Resource(name="userDao2")//默认按名称,名称找不到时,通过byType
@Resource(name="userDaoImpl") //name的指定配合@Component("userDaoImpl")的使用
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@PreDestroy
public void destroy(){
System.out.println("==========destroy");
}
}
3、test
package dhp.service;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import dhp.dao.UserDao;
import dhp.model.User;
public class UserServiceTest {
@Test
public void testAdd() {
//ClassPathXmlApplicationContext继承自ApplicationContext,而ApplicationContext继承自BeanFactory
//推荐使用
ClassPathXmlApplicationContext ctx =new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) ctx.getBean("userService");
userService.add(new User());
System.out.println(userService.getUserDao());
ctx.destroy();
}
}
4、beans.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"
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">
<!-- 初始化了AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor,
PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor -->
<context:annotation-config/> <!-- 初始化4个 --> <!-- @autowired, @resource -->
<context:component-scan base-package="dhp"/> <!-- 扫描@Component @Service @Controller @Repository 减少bean配置 -->
<!-- <bean id="userDao" class="dhp.dao.impl.UserDaoImpl">
<property name="daoId" value="100"></property>
</bean>
<bean id="userDao2" class="dhp.dao.impl.UserDaoImpl">
<property name="daoId" value="200"></property>
</bean> -->
<!-- <bean id="userService" class="dhp.service.UserService">
</bean>
-->
</beans>
附:
1.bean的自动装配和自动检测的区别
启用注解装配,在xml配置文件里添加:<context:annotation-config/>
启用自动扫描注解,在xml配置文件里添加:<context:component-scan base-package="dhp"/>
二者的区别: 自动装配表示通过@Autowired, @Inject, @Resource等实现对属性或构造函数的自动注入;仍然需要在配置文件里定义bean,只是通过
自动装配省去了property和constructor-arg的配置。 自动检测是扫描特定的注解(包括:@Component, @Controller, @Service, @Repository),将注
解过的类自动定义为bean,自动检测是自动装配的超集,通过自动检测,可以省去在xml配置文件里定义bean了。
2. 通过自动装配和注解实现注入
在xml配置文件里启动注解装配:<context:annotation-config/>
定义bean:
<bean id="userDao" class="dhp.dao.impl.UserDaoImpl">
<property name="daoId" value="100"></property>
</bean>
然后在需要注入的属性上或者其setter方法上,或者构造函数上,添加@Autowired, @Inject, @Resource等注解实现自动注入:
//set方式注入
//@Autowired
//@Inject
@Resource
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Autowired, @Inject, @Resource的区别:@Autowired是Spring 3.0的注解,是通过byType形式实现注解,可以通过@Qualifier根据bean的id进行限定;使用@Autowired注解即引入了对Spring的依赖。@Inject是JSR 330的注解,使用该注解需要导入包javax.inject,@Named(value=”“)可以根据bean的id进行限定;@Resource是JSR 250的注解,可以通过value限定bean的id,如@Resource(value=””);