在平时的java开发中,想在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,Spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过Spring的IOC容器帮我们new指定实例并且将实例注入到需要该对象的类中来。依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做。
下面我们来看下Spring注入的几种方式:
[b]1、Setter方法注入,这是最常用的方式;[/b]
假设有一个UserServiceImpl,类中需要实例化一个UserDao对象,那么就可以定义一个UserDao的成员变量,然后提供setter方法(ioc的注入入口),下面请看Java代码:
相应xml的配置,比较简单:
[b] 2、构造器注入,该方式是第二常用的方式;[/b]
同样的假设有一个UserServiceImpl,类中需要实例化一个UserDao和roleDao对象,那么就定义UserDao和roleDao的成员变量,然后提供构造方法(ioc的注入入口),下面请看Java码:
同样的,我们来看下xml配置文件,index来表示参数在构造器中的先后顺序
[b] 3、静态工厂方法注入[/b]
静态工厂方法注入就是通过调用静态工厂的方法来获取自己需要的对象,为了让Spring管理所有对象,我们不能直接通过"类名.静态方法"来获取对象,而是依然通过Spring注入的形式获取:
下面我们来看一个例子
静态工厂
配置文件如下:
[b] 4、实例工厂方法注入[/b]
实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先new工厂类(比静态工厂方法注入多一个配置),再调用普通的实例方法:
实例工厂
xml的配置如下:
[b]注意:[/b]
以上方式创建出来的对象都是单例的,如果需要多例对象,则需要在xml配置上scope属性为prototype,以下:
下面我们来看下Spring注入的几种方式:
[b]1、Setter方法注入,这是最常用的方式;[/b]
假设有一个UserServiceImpl,类中需要实例化一个UserDao对象,那么就可以定义一个UserDao的成员变量,然后提供setter方法(ioc的注入入口),下面请看Java代码:
package com.billy.service.impl;
public class UserServiceImpl{
private UserDao userDao;//注入对象
public List<User> findUserList(){
return userDao.findUserList();//这里就可以使用userDao对象了
}
public void setUserDao(UserDao userDao){//需要提供注入对象的setter方法
this.userDao = userDao;
}
}
相应xml的配置,比较简单:
<bean id="userService" class="com.billy.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.billy.dao.impl.UserDaoImpl"/>
[b] 2、构造器注入,该方式是第二常用的方式;[/b]
同样的假设有一个UserServiceImpl,类中需要实例化一个UserDao和roleDao对象,那么就定义UserDao和roleDao的成员变量,然后提供构造方法(ioc的注入入口),下面请看Java码:
package com.billy.service.impl;
public class UserServiceImpl{
private UserDao userDao;//注入对象1
private RoleDao roleDao;//注入对象2
//需要提供构造器,并且参数为需要注入的对象
public UserServiceImpl(UserDao userDao,RoleDao roleDao){
this.userDao = userDao;
this.roleDao = roleDao;
}
public List<User> findUserList(){
return userDao.findUserList();
}
public List<Role> findRoleList(){
return roleDao.findRoleList();
}
}
同样的,我们来看下xml配置文件,index来表示参数在构造器中的先后顺序
<bean id="userService" class="com.billy.service.impl.userServiceImpl">
<constructor-arg index="0" ref="userDao"/>
<constructor-arg index="1" ref="roleDao"/>
</bean>
<bean id="userDao" class="com.billy.dao.impl.UserDaoImpl"/>
<bean id="roleDao" class="com.billy.dao.impl.RoleDaoImpl"/>
[b] 3、静态工厂方法注入[/b]
静态工厂方法注入就是通过调用静态工厂的方法来获取自己需要的对象,为了让Spring管理所有对象,我们不能直接通过"类名.静态方法"来获取对象,而是依然通过Spring注入的形式获取:
下面我们来看一个例子
静态工厂
package com.billy.common.util;
public class TimeUtils {
/**
* 根据时间表达式转换为毫秒(静态方法)
*
* @param expr
* @return
*/
public static long getMillisionSecond(String expr) {
if (StringUtils.isEmpty(expr)) {
return -1;
}
if (expr.endsWith("ms")) {
return Long.parseLong(expr.replaceAll("", "ms"));
} else if (expr.endsWith("sec")) {
expr = expr.replaceAll("sec", "");
return Long.parseLong(expr) * 1000;
} else if (expr.endsWith("min")) {
expr = expr.replaceAll("min", "");
return Long.parseLong(expr) * 1000 * 60;
} else if (expr.endsWith("hour")) {
expr = expr.replaceAll("hour", "");
return Long.parseLong(expr) * 1000 * 60 * 60;
} else if (expr.endsWith("day")) {
expr = expr.replaceAll("day", "");
return Long.parseLong(expr) * 1000 * 60 * 60 * 24;
} else if (expr.endsWith("week")) {
expr = expr.replaceAll("week", "");
return Long.parseLong(expr) * 1000 * 60 * 60 * 24 * 7;
} else if (expr.endsWith("month")) {
expr = expr.replaceAll("month", "");
return Long.parseLong(expr) * 1000 * 60 * 60 * 24 * 30;
} else {
throw new IllegalArgumentException("illegal expression arg");
}
}
}
package com.billy.common.util;
public class SpringProperty{
private Long refreshTime;
public void setRefreshTime(Long refreshTime){
this.refreshTime = refreshTime;
}
}
配置文件如下:
<bean id="springProperty" class="com.billy.common.util.SpringProperty">
<property name="refreshTime">
<bean class="com.billy.common.util.TimeUtils" factory-method="getMillisionSecond">
<constructor-arg>
<value>${index.refresh.time}</value>
</constructor-arg>
</bean>
</property>
</bean>
[b] 4、实例工厂方法注入[/b]
实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先new工厂类(比静态工厂方法注入多一个配置),再调用普通的实例方法:
实例工厂
package com.billy.util.factory;
public class UserDaoFactory{
public UserDao getUserDaoImpl(){
return new UserDaoImpl();
}
}
package com.billy.service.impl;
public class UserServiceImpl{
private UserDao userDao;
public List<User> findUserList(){
return userDao.findUserList();
}
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
}
xml的配置如下:
<bean id="userService" class="com.billy.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
<!--要先实例化工厂类-->
<bean id="userDaoFactory" class="com.billy.util.factory.userDaoFactory"/>
<!-- 注意factory-bean写实例化的工厂,即上面实例化出来的
factory-method写工厂方法即可 -->
<bean id="userDao" factory-bean="userDaoFactory" factory-method="getUserDaoImpl"/>
[b]注意:[/b]
以上方式创建出来的对象都是单例的,如果需要多例对象,则需要在xml配置上scope属性为prototype,以下:
<bean id="..." class="..." scope="prototype"/>