Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架。
struts是web框架,Hibernate是O/RM框架
Spring是容器框架,用于配制bean并维护bean之间关系的框架。
Spring中有一个重要概念:Bean(是Java中的任何一种对象,javaBean、service、action、数据源、DAO等)
IoC,控制反转,Inverse of Control,或者DI(Dependency Injection 依赖注入)
开发一个spring项目,这里使用3.2.17版的
创建一个简单的maven项目SpringDemo,在pom.xml中写入:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.17.RELEASE</version>
</dependency>
创建spring的一个核心文件 :applicationContext.xml(spring的配置文件,默认名字,也可以起别的名字)【hibernate有核心hibernate.cfg.xml,struts核心文件struts.xml】,该文件一般放在src目录下
该版本的配置文件:
<?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-3.2.xsd" >
.....
<!--这里写bean-->
</beans>
下面编写我们的测试代码:
平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统 一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类 中。依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们 程序员来做而是交给spring容器来做。
我在这模拟项目中的业务层和Dao层
spring有多种依赖注入的形式,这里使用了Set注入,即我们不再具体的类中手动new对象,把它交给spring操作
set注入
Biz层
UserBiz.java
package com.lgh.spring.biz;
public interface UserBiz {
public void save();
}
实现
UserBizImpl.java
package com.lgh.spring.biz.impl;
import com.lgh.spring.biz.UserBiz;
import com.lgh.spring.dao.UserDao;
public class UserBizImpl implements UserBiz {
private UserDao userDao;
public UserBizImpl() {
System.out.println("UserBizImpl 构造方法");
}
@Override
public void save() {
System.out.println("UserBizImpl ------------");
userDao.save();
}
public void setUserDao(UserDao userDao) {
System.out.println("setUserDao set");
this.userDao = userDao;
}
}
Dao层:
UserDao.java
package com.lgh.spring.dao;
public interface UserDao {
void save();
}
UserDaoMysqlImpl.java
package com.lgh.spring.dao.impl;
import com.lgh.spring.dao.UserDao;
public class UserDaoMysqlImpl implements UserDao {
public UserDaoMysqlImpl() {
System.out.println("UserDaoMysqlImpl 构造方法");
}
@Override
public void save() {
System.out.println("UserDaoMysqlImpl save方法");
}
}
准备已经做好了,我们之后要在spring的xml文件中进行配置
随后编写spring的xml文件,中的id属性是class属性的一个别名,class属性指类的全名,因为在UserBizImpl.java中有一个公共属性userDao,所以要在标签中创建一个标签指定userDao。标签中的name就是UserBizImpl类中的userDao属性名,ref指下面,这样其实是spring将UserBizImpl对象实例化并且调用UserBizImpl的setUserDao方法将userDao注入:
<bean id="userDao" class="com.lgh.spring.dao.impl.UserDaoMysqlImpl" lazy-init="true" >
</bean>
<bean id="userBiz" class="com.lgh.spring.biz.impl.UserBizImpl" lazy-init="true">
<property name="userDao" ref="userHib"></property>
</bean>
测试:
SpringTest01.java
package com.lgh.spring.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.lgh.spring.biz.UserBiz;
public class SpringTest01 {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserBiz userBiz = (UserBiz) ac.getBean("userBiz");
userBiz.save();
}
}
执行结果:
UserBizImpl 构造方法
UserDaoMysqlImpl 构造方法
setUserDao set
UserBizImpl ------------
UserDaoMysqlImpl save方法
通过执行结果我们看到spring在帮我们创建对象时,调用了实现类的构造方法
构造器注入
这种方式的注入是指带有参数的构造函数注入,修改上面的例子,我创建了两个成员变量userDao,但是并未设置对象的set方法,所以就不能支持第一种注入方式,这里的注入方式是在UserBizImpl的构造函数中注入,也就是说在创建UserBizImpl对象时要将userDao参数值传进来:
UserBizConstrImpl.java
package com.lgh.spring.biz.impl;
import com.lgh.spring.biz.UserBiz;
import com.lgh.spring.dao.UserDao;
public class UserBizConstrImpl implements UserBiz {
private UserDao userDao;
public UserBizConstrImpl(UserDao userDao) {
this.userDao = userDao;
System.out.println("构造方法注入方式");
}
@Override
public void save() {
userDao.save();
}
}
在XML文件中同样不用的形式,而是使用标签,ref属性同样指向其它标签的id属性:
<bean id="userConBiz" class="com.lgh.spring.biz.impl.UserBizConstrImpl" lazy-init="true">
<!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置-->
<constructor-arg ref="userDao"></constructor-arg>
</bean>
测试:
package com.lgh.spring.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.lgh.spring.biz.UserBiz;
public class SpringTest04 {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserBiz userBiz = (UserBiz) ac.getBean("userConBiz");
userBiz.save();
}
}
UserDaoMysqlImpl 构造方法
构造方法注入方式
UserDaoMysqlImpl save方法
有时候,构造方法中传递的参数有多个我们用以下方法可以解决构造方法参数的不确定性
下面是设置index,就是参数位置:
<bean id="userConBiz" class="com.lgh.spring.biz.impl.UserBizConstrImpl" lazy-init="true">
<!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置-->
<constructor-arg index="0" ref="userDao"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean>
另一种是设置参数类型:
<constructor-arg type="java.lang.String" ref=""/>
当参数为非字符串类型时,在配置文件中需要制定类型,如果不指定类型一律按照字符串类型赋值。
当参数类型不一致时,框架是按照字符串的类型进行查找的,因此需要在配置文件中制定是参数的位置