Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以IOC(翻转控制)和AOP(面向切面编程)为内核
提供了展现层SpringMVC和持久层Spring JDBCTemplatey以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多的第三方框架和类库,逐渐成为使用最多的Java EE企业级应用开源框架
1、方便解耦,简化开发
通过Spring提供的IOC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的多度耦合,用户不必再为单例模式、属性文件解析等这些底层的需求编写代码,可以更专注于上层的应用
2、AOP编程的支持
通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现
3、声明式事务的支持
可以将我们从单调烦闷的事务代理代码中解脱出来,通过声明式灵活的进行事务管理,提高开发效率和质量
4、方便程序的测试
可以用非容器依赖的编程方式进行几乎所欲的测试工作,测试不再是昂贵的操作,而是随手可做的事情
5、方便继承各种优秀的框架
Spring对各种优秀的框架(Struts、Hibemate、Hessian、Quartz等)的支持
6、降低Java EE API的使用难度
Spring 对Java EE API(JDBC、JavaMail、远程调用等)进行了薄薄的封装,使用这些API的使用难度大为降低
7、Java源码是经典的学习范例
Spring的源代码设计精妙,结构清晰,匠心独具,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣
1、导入Spring开发的基本包坐标
org.springframework spring-context 5.3.7
2、编写Dao接口和实现类
UserDao接口
package com.zg.dao;
public interface UserDao {
public void save();
}
UserDao实现类
package com.zg.dao.impl;
import com.zg.dao.UserDao;
public class userDaoIMPL implements UserDao {
@Override
public void save() {
System.out.println("save running.....");
}
}
3、创建Spring核心配置文件
4、在Spring配置文件中配置UserDaoImpl
5、使用Spring的API获得Bean实例
package com.zg.demo;
import com.zg.dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
public class UserDaoDemo {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao)app.getBean("userDao");
userDao.save();
}
}
Spring配置文件详解
Bean标签基本配置
用于配置对象交由Spring来创建
默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功
id:Bean实例在Spring容器中的唯一标识
class:Bean的全限定名称
scope:指令对象的作用范围
1、当scope的取值为singleton时
Bean的实例化个数为1个
Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
Bean的声明周期:
对象创建:当应用加载,创建容器时,对象就被创建了
对象运行:只要容器在,对象一直活着
对象销毁:当应用卸载时,销毁容器时,对象就被销毁了
2、当scope的取值为prototype时
Bean的实例化个数为多个
Bean的实例化时机:当调用getBean()方法时,实例化配置的Bean实例
Bean的声明周期:
对象创建:当使用对象时,创建新的对象实例
对象运行:只要对象在使用中,对象一直活着
对象销毁:对象长时间不用,被Java的垃圾回收器回收
init-method:指定类中的初始化方法名称
destroy-method:指定类中销毁方法名称
1、无参构造方法实例化
以上方式都为无参构造方法实例化
public class userDaoIMPL implements UserDao {
public userDaoIMPL() {
}
}
2、工厂静态方法实例化
package com.zg.factory;
import com.zg.dao.UserDao;
import com.zg.dao.impl.userDaoIMPL;
//工厂静态方法实例化
public class StaticFactory {
public static UserDao getUserDao(){
return new userDaoIMPL();
}
}
在获取全类名时可以右键其名称选择Copy Reference
3、工厂实例方法实例化,很多
package com.zg.factory;
import com.zg.dao.UserDao;
import com.zg.dao.impl.userDaoIMPL;
//工厂静态方法实例化
public class StaticFactory {
public static UserDao getUserDao(){
return new userDaoIMPL();
}
}
Spring配置文件
创建service层,不使用Spring
当我们不使用Spring,在service层中我们需要通过UserServiceImpl实现类来重写UserService中的save()方法,然后调用通过Spring获取Dao层中UserDao的实现类UserDaoImpl对象的save方法(业务层save调用Dao层save),然后web层中通过UserService userService = new UserServiceImpl(); 获取service,来实现dao层的具体业务,这里因为service层没有配置到Spring容器中。
1、创建UserService,UserServie内部调用UserDao的save()方法
package com.zg.service.impl;
import com.zg.dao.UserDao;
import com.zg.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserServiceImpl implements UserService {
@Override
public void save() {
//UserService要调UserDao,但现在UserDao已经在Spring产生
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao)app.getBean("userDao");
userDao.save();
}
}
2、web层不使用Spring来封装service
package com.zg.demo;
import com.zg.service.UserService;
import com.zg.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserController {
//它的内部需要获得Service
public static void main(String[] args) {
//不使用Spring封装service
UserService userService = new UserServiceImpl();
userService.save();
}
}
将service层也配置到Spring容器中
1、在配置文件applicationContext.xml中将UserServiceImpl的创建权交给Spring
2、从Spring容器中获得UserService进行操作
package com.zg.demo;
import com.zg.service.UserService;
import com.zg.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserController {
//它的内部需要获得Service
public static void main(String[] args) {
//使用Spring封装service
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService");
userService.save();
}
}
问题分析
目前UserSrvice实例和UserDao实例都存在于Spring中,当前的做法是在容器外部获取UserService实例和UserDao实例,然后再程序中进行结合
因为UserService和UserDao都在Spring容器中,而最终程序直接使用的是UserService,所以可以在Spring容器中,将UserDao设置到UserService内部
依赖注入(Dependency Injection):它是Spring框架核心IOC的具体实现
在编写程序时,通过控制反转,把对象的创建交给了Spring,但是代码中不可能出现没有依赖的情况。
IOC解耦只是降低他们之间的关系,但不会消除(业务层仍然会调用持久层的方法)
那这种业务层和持久层的依赖关系,在使用Spring后,使用Spring来维护,也就是等框架把持久层对象传入入业务层,不用我们获取
Bean的依赖注入方式将UserDao注入到UserService内部可通过有参的构造方法和set方法来实现
set方法注入(注入对象)1、在UserServiceImpl中添加setUserDao方法
package com.zg.service.impl;
import com.zg.dao.UserDao;
import com.zg.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
//我们不用从容器获取Dao,因为在容器内部已经将Dao通过set方法注入给了service
userDao.save();
}
}
2、配置Spring容器中调用set方法进行注入
但是但是,在web层就不能new一个UserService啦,因为它没有获取UserDao的注入,所以在web层只能使用通过Spring封装的service来调用dao的方法
set方法注入的简单方式–>P命名空间注入P命名空间注入的本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中
xmlns:p="http://www.springframework.org/schema/p"
然后将下面的代码1进行更换为代码2就行
代码1:
代码2:
构造注入(有参构造)
1、创建有参构造
package com.zg.service.impl;
import com.zg.dao.UserDao;
import com.zg.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserServiceImpl implements UserService {
private UserDao userDao;//有参构造
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
public UserServiceImpl() {//无参构造
}
@Override
public void save() {
//我们不用从容器获取Dao,因为在容器内部已经将Dao通过set方法注入给了service
userDao.save();
}
}
2、构造方法注入
Bean的依赖注入的数据类型
set和有参构造方法都是注入的引用Bean,除了对象的引用可以注入,普通数据类型,集合等都可以在容器中进行注入
注入数据的三种数据类型
普通数据类型
引用数据类型
集合数据类型
package com.zg.dao.impl;
import com.zg.dao.UserDao;
public class userDaoImpl implements UserDao {
private String username;
private int age;
public void setUsername(String username) {
this.username = username;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void save() {
System.out.println(username+"===="+age);
System.out.println("save runningg.....");
}
}
集合数据类型的注入
package com.zg.dao.impl;
import com.zg.dao.UserDao;
import com.zg.domain.User;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class userDaoImpl implements UserDao {
private List strList;
private Map userMap;
private Properties properties;
public void setStrList(List strList) {
this.strList = strList;
}
public void setUserMap(Map userMap) {
this.userMap = userMap;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
private String username;
private int age;
public void setUsername(String username) {
this.username = username;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void save() {
//System.out.println(username+"===="+age);
System.out.println("save runningg.....");
System.out.println(strList);
System.out.println(userMap);
System.out.println(properties);
}
}
aaa bbb ccc ppp1 ppp3 ppp4
Map集合中准备的user
package com.zg.domain;
public class User {
private String name;
private String addr;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
@Override
public String toString() {
return "User{" +
"name='" + name + ''' +
", addr='" + addr + ''' +
'}';
}
}
引入其他配置文件(分模块开发)
实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载
如果不使用set方法注入而使用构造方法引用,则标签和标签内部的配置写法一样。
Spring相关API ApplicationContext的继承体系applicationContext:接口类型,代表应用上下文,可以通过其实例获得Spring容器中的Bean对象
1、ClassPathXmlApplicationContext:从类的根路径下加载配置文件推荐使用
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
2、FileSystemXmlApplicationContext:从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置
在项目名称上右键选择Copy path即可复制文件在磁盘上的路径
FileSystemXmlApplicationContext fileSystemXmlApplicationContext = new FileSystemXmlApplicationContext("D:\java\Spring\src\main\resources\applicationContext.xml");
3、AnnotationConfigApplicationContext:使用注解配置容器对象时,需要使用此类来创建spring容器,用来读取注解
getBean()方法的使用使用ID:UserService userService = (UserService) app.getBean("userService");允许容器中存在相同类型的Bean
使用字节码类型:UserService userService1 = app.getBean(UserService.class);
其中,当参数的数据类型是字符串时,表示根据Bean的id从容器中获得Bean实例,返回是Object,需要强转。当参数的数据类型是Class时,表示根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,则此方法会报错。



