目录
运行时,出现java.lang.NoClassDefFoundError: org/springframework/core/metrics/ApplicationStartup
使用Spring集成Junit完成JdbcTemplate修改和删除
PlatformTransactionManager平台事务管理
1、SqlSession工厂构建器SqlSessionFactoryBuilder
运行时发现 xxx cannot be cast to xxx
Spring是分层的JavaSE/EE应用full-stack轻量级开源框架,以loC(InverseOfControl:反转控制)和 AOP(AspectOrientedProgramming:面向切面编程)为内核。
提供了展现层SpringMVC和持久层Spring JDBCTemplate以及业务展事务管理等众多的企业级应用技术还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的JavaEE企业应用开源框架。
1997年,IBM提出了EJB的思想
1998年,SUN制定开发标准规范EJB1.0
1999年,EJB1.1发布
2001年,EJB2.0发布
2003年,EJB2.1发布
2006年,EJB3.0发布
Rod Johnson(Spring之父)
ExpertOne-to-OneJ2EEDesignand Development(2002)
阐述了J2EE使用EJB开发设计的优点及解决方案
ExpertOne-to-OneJ2EEDevelopment without EJB(2004)
阐述了J2EE开发不使用EJB的解决方式(Spring雏形)
2017年9月份发布了Spring的最新版本 Spring5.0通用版(GA)
①方便解耦,简化开发
通过Spring提供的loC容器,可以将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的过度耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
②AOP编程的支持
通过Sprina的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现
③声明式事务的支持
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量
④方便程序的测试
可以用非容器依赖的编程方式进行几平所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情
⑤方便集成各种优秀框架
Spring对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的支持。
⑥降低JavaEE API的使用难度
Spring对JavaEEAPI(如JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些API的使用难度大为降低
⑦Java 源码是经典学习范例
Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。它的源代码无意是Java技术的最佳实践的范例。

①导入Spring开发的基本包坐标
②编写Dao接口和实现类
③创建Spring核心配置文件
④在Spring配置文件中配置UserDaoImpl
⑤使用Spring的API获得Bean
这种 方式完成了解耦,后续只需要给配置文件即可

①:在pom.xml中配置spring的坐标
- <dependencies>
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-contextartifactId>
- <version>5.0.5.RELEASEversion>
- dependency>
-
- dependencies>
②:在src下创建com.Dao.UserDao

创建一个接口
- public interface UserDao {
- public void play();
- }
创建UserDao的实现类
- import com.Dao.UserDao;
-
- public class UserDaoImpl implements UserDao {
- public void play(){
- System.out.println("play and play...");
- }
- }

③:创建spring核心配置文件(文件的名字任意)

一般起名为applicationContext.xml
④在Spring配置文件中配置UserDaoImpl(id任意)
id="userDao" class="com.Dao.impl.UserDaoImpl">

⑤:使用springAPI获得Bean
创建一个Demo包下的UserDemo

- import com.Dao.UserDao;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class UserDemo {
- public static void main(String[] args) {
- ApplicationContext app =new ClassPathXmlApplicationContext("applicationContext.xml");
- UserDao userDao = (UserDao) app.getBean("userDao");
- userDao.play();
- }
- }
运行之后:

用于配置对象交由Spring来创建
默认情况下他调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功。
基本属性:
id:Bean实例在Spring容器中的唯一标识
class:Bean的限定名称
scope:指对象的作用范围,取值如下:
| 取值范围 | 说明 |
| singleton | 默认值,单例的 |
| prototype | 多例的 |
| request | WEB项目中,Spring创建一个Bean的对象,将对象存入到request域中 |
| session | WEB项目中,Spring创建一个Bean的对象,将对象存入到session域中 |
| global session | WEB项目中,应用在Portlet环境,如果没有Porlet环境那么globalSession相当于session |
下pom.xml中配置junit的坐标
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>4.11version>
- dependency>
在test模块下创建text类
- package com;
-
- import com.Dao.UserDao;
- import org.junit.Test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class text {
- @Test
- public void text1(){
- ApplicationContext app =new ClassPathXmlApplicationContext("applicationContext.xml");
- UserDao userDao1 = (UserDao) app.getBean("userDao");
- UserDao userDao2 = (UserDao) app.getBean("userDao");
- System.out.println(userDao1);
- System.out.println(userDao2);
-
- }
- }

使用singleton打印出来的地址一致说明容器中只有一份

使用prototype打印出来的地址不一致说明容器中有多份

1)当scope的取值为singleton时
Bean的实例化个数:1个
Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
Bean的生命周期:
2)当scope取值为prototype时
Bean的实例化个数:多个
Bean的实例化时机:当调用getBean()方法时实例化Bean
Bean的生命周期
init-method:指定类中的初始化方法名称
destory-method:指定类中的销毁方法名称
在UserDaoImp类下
创建的初始化方法init和销毁方法destory(名字为任意的)
-
- public class UserDaoImpl implements UserDao {
- public void play(){
- System.out.println("play and play...");
- }
- public UserDaoImpl(){
- System.out.println("UserDaoImpl被创建");
- }
- public void init(){
- System.out.println("初始化方法");
- }
- public void destory(){
- System.out.println("销毁方法");
- }
- }
在applicationContext.xml文件中指定初始化和销毁方法
- <bean id="userDao" class="com.Dao.impl.UserDaoImpl"
- init-method="init" destroy-method="destory"
- >bean>
在UserDemo方法运行结果:

无参构造方法实例化
工厂静态方法实例化
工厂实例方法实例化
①:工厂静态方法实例化
创建一个factory包下
- package com.factory;
-
- import com.Dao.UserDao;
- import com.Dao.impl.UserDaoImpl;
-
- public class StaticFactory {
- public static UserDao getUserDao(){
- return new UserDaoImpl();
- }
- }
xml中配置:
<bean id="userDao" class="com.factory.StaticFactory" factory-method="getUserDao">bean>

在userDemo下运行,或者在test运行也可

② 工厂实例方法实例化演示
创建一个DynamicFactory类
- import com.Dao.UserDao;
- import com.Dao.impl.UserDaoImpl;
-
- public class DynamicFactory {
- public UserDao getUserDao(){
- return new UserDaoImpl();
- }
- }

在applicationContext.xml中
- <bean id="factory" class="com.factory.DynamicFactory" >bean>
- <bean id="userDao" factory-bean="factory" factory-method="getUserDao">bean>

其余代码不变,在text下运行得

创建一个Service服务层的接口和实现类
接口中写入
- public interface UserService {
- public void save();
- }
service服务层的实现类去实现save方法
- public class UserServiceImpl implements UserService {
-
- @Override
- public void save() {
-
- ApplicationContext app =new ClassPathXmlApplicationContext("applicationContext.xml");
- UserDao userDao = (UserDao) app.getBean("userDao");
- userDao.save();
-
- }
- }
dao持久层下的接口和实现类
- public interface UserDao {
- public void save();
-
- }
实现类下
- public class UserDaoImpl implements UserDao {
- public void save(){
- System.out.println("run save...");
- }
- }
resource下的applicationContext.xml下
- "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">
-
- <bean id="userDao" class="com.Dao.impl.UserDaoImpl">bean>
- <bean id="userService" class="com.Service.Impl.UserServiceImpl">bean>
-
-
- beans>
在demo包下模拟web环境的创建一个UserController
- import com.Service.UserService;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class UserController {
- public static void main(String[] args) {
- ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
- UserService userService = (UserService) app.getBean("userService");
- userService.save();
- }
- }
运行之后

上面的缺点也很明显,是同时获取service和dao层的到时我们只想要service层,所以此时,需要依赖注入,把dao注入到service服务层
依赖注入(DependencyInjection):它是Spring框架核心IOC的具体实现。
在编写程序时,通过控制反转,把对象的创建交给了Spring,但是代码中不可能出现没有依赖的情况。 IOC解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。
那这种业务层(Service)和持久层(Dao)的依赖关系,在使用Spring之后,就让Spring来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。
构造方法和set方法
法1:set方法
在UserServiceImpl下创建userDao
- import com.Dao.UserDao;
- import com.Service.UserService;
-
-
- public class UserServiceImpl implements UserService {
- private UserDao userDao;
-
- public void setUserDao(UserDao userDao) {
- this.userDao = userDao;
- }
-
- @Override
- public void save() {
- userDao.save();
- }
- }
在applicationContext.xml文件中配置
- <bean id="userDao" class="com.Dao.impl.UserDaoImpl">bean>
- <bean id="userService" class="com.Service.Impl.UserServiceImpl">
- <property name="userDao" ref="userDao">property>
-
- bean>
然后之前创建的UserController就可以启动了

如果直接new UserServiceImpl对象会报空指针异常的错,

因为useDao是不是通过spring容器来获取的,自然就是null值了
P命名空间注入本质也是set方法注入,但比起上述的set方法更加方便,首先需要引入p命名空间:
xmlns:p="http://www.springframework.org/schema/p"
修改注入方式
<bean id="userService" class="com.Service.Impl.UserServiceImpl" p:userDao-ref="userDao">

是一个对象就用-ref,普通属性就不用
userController运行之后

在applicationContext.xml文件中
- <bean id="userService" class="com.Service.Impl.UserServiceImpl">
- <constructor-arg name="userDao" ref="userDao">constructor-arg>
- bean>
userServiceImpl下

运行结果:

上面的操作,都是注入引用Bean,除了对象的引用可以注入,普通数据类型,集合都可以在容器中进行注入。
注入数据的三种数据类型
普通数据注入,如在UserDao层注入两个普通数据类型(采用set方式注入)
- public class UserDaoImpl implements UserDao {
-
- private String name;
- private int age;
-
- public void setName(String name) {
- this.name = name;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public void save(){
- System.out.println("姓名:"+name+"年龄:"+age);
- System.out.println("run save...");
- }
- }
在applicationContext.xml文件中,在配置dao中设置参数
- <bean id="userDao" class="com.Dao.impl.UserDaoImpl">
- <property name="name" value="李四"/>
- <property name="age" value="20" />
- bean>
在Usercontroller下
- public class UserController {
- public static void main(String[] args) {
- ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
- UserService userService = (UserService) app.getBean("userService");
- userService.save();
-
- }
- }
运行结果

在UserDaoImpl下
采用set注入方式,设置集合,提供对应得set方法
- package com.Dao.impl;
-
- import com.Dao.UserDao;
- import com.pojo.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;
- }
-
- public void play(){
-
- System.out.println("play and play...");
- }
- public void save(){
- System.out.println("List集合-》"+strList);
- System.out.println("Map集合-》"+userMap);
- System.out.println("properties集合-》"+properties);
- System.out.println("run save...");
- }
- }
在applicationContext.xml下配置注入值
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-
- <bean id="userDao" class="com.Dao.impl.UserDaoImpl">
-
- <property name="strList" >
- <list>
- <value>慧慧value>
- <value>孔超value>
- <value>宝value>
- list>
- property>
- <property name="userMap">
- <map>
-
- <entry key="宝1" value-ref="user1">entry>
- <entry key="宝2" value-ref="user2">entry>
- map>
- property>
-
-
- <property name="properties">
- <props>
- <prop key="p1">宝1prop>
- <prop key="p2">宝2prop>
- props>
- property>
- bean>
- <bean id="user1" class="com.pojo.User">
- <property name="name" value="慧慧"/>
- <property name="address" value="赣州"/>
- bean>
- <bean id="user2" class="com.pojo.User">
- <property name="name" value="孔超"/>
- <property name="address" value="赣州"/>
- bean>
-
-
- <bean id="userService" class="com.Service.Impl.UserServiceImpl">
- <constructor-arg name="userDao" ref="userDao">constructor-arg>
- bean>
-
- beans>
在UserController测试下
- import com.Service.UserService;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class UserController {
- public static void main(String[] args) {
- ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
- UserService userService = (UserService) app.getBean("userService");
- userService.save();
-
- }
- }
运行结果:

实际开发中,Spring的配置内容非常的多,这就导致Spring配置很繁琐且体积很大,所以可以将部分配置拆解到其他配置文件中,而且主配置文件通过import标签进行加载
语法格式:
<import resource="xxxx.xml"/>
标签
applicationContext:接口类型,代表应用上下文,可以通过其实例获得Spring容器中的Bean对象

紫色的为接口,浅绿色的为抽象类,绿色的为实现类
①ClassPathXmlApplicationContext
它是从类的跟路径下加载配置文件,只需要创建resource下的xml,参数写入xxx.xml即可(推荐使用)

②FileSystemXmlApplicationContext
他是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。

③AnnotationConfigApplicationContext
当使用注解配置容器对象时,需要食用此类来创建spring容器骂他用来读取注解
- //根据id找
- public object getBean(String name) throws BeansException {
- assertBeanFactoryActive();
- return getBeanFactory().getBean(name);
- }
-
- //根据字节码对象找
- public
T getBean(Class requiredType) throws BeansException { - assertBeanFactoryActive();
- return getBeanFactory().getBean(requiredType);
- }
其中,当参数的数据类型是字符串时,表示根据Bean的id从容器这种获得Bean实例,返回Object,需要强转。当参数的数据类型是Class类型是,表示根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个是是,则clss方法会报错
根据id

根据字节码对象

某一类型的bean对象存在多对时,只能使用id,因为id是唯一的,某一类型的bean对象存在一对是时,可以用id,也可以使用字节码对象,使用字节码对象更方便些。

常见的数据源(连接池):DBCP、C3P0、BoneCP、Druid等
①:导入数据源坐标
-
- <dependencies>
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- <version>5.1.32version>
- dependency>
- //c3p0数据源
- <dependency>
- <groupId>c3p0groupId>
- <artifactId>c3p0artifactId>
- <version>0.9.1.2version>
- dependency>
- //druid数据源
- <dependency>
- <groupId>com.alibabagroupId>
- <artifactId>druidartifactId>
- <version>1.1.10version>
- dependency>
-
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>4.11version>
- <scope>testscope>
- dependency>
- dependencies>
在test测试中创建类
- package com.test;
-
- import com.mchange.v2.c3p0.ComboPooledDataSource;
- import org.junit.Test;
-
- import java.sql.Connection;
-
- public class DateSourceTest {
- @Test
- public void test1() throws Exception{
- ComboPooledDataSource dataSource=new ComboPooledDataSource();
- dataSource.setDriverClass("com.mysql.jdbc.Driver");
- //访问数据库中kc_db01库
- dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/kc_db01");
- //数据库的账号密码
- dataSource.setUser("root");
- dataSource.setPassword("123456");
- Connection connection=dataSource.getConnection();
- System.out.println(connection);
- connection.close();
- }
- }
运行结果

打印出地址说明连接成功
测试连接druid
-
- @Test
- public void test2() throws Exception{
- DruidDataSource dataSource=new DruidDataSource();
- dataSource.setDriverClassName("com.mysql.jdbc.Driver");
- //访问数据库中kc_db01库
- dataSource.setUrl("jdbc:mysql://localhost:3306/kc_db01");
- //数据库的账号密码
- dataSource.setUsername("root");
- dataSource.setPassword("123456");
- Connection connection=dataSource.getConnection();
- System.out.println(connection);
- connection.close();
- }

在resource资源下创建一个MyJdbc.properties文件测试c3p0数据源)
内容是:
- jdbc.driver=com.mysql.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/kc_db01
- jdbc.username=root
- jdbc.password=123456
在测试类中:
- @Test
- //测试手动创建c3p0数据库源(加载properties配置文件)
- public void test3() throws Exception{
- //读取配置文件,获取的参数是你设置的配置文件的名字,
- ResourceBundle rb=ResourceBundle.getBundle("MyJdbc");
- String driver=rb.getString("jdbc.driver");
- String url=rb.getString("jdbc.url");
- String username=rb.getString("jdbc.username");
- String password=rb.getString("jdbc.password");
- //创建数据源对象,设置连接参数
- ComboPooledDataSource dataSource=new ComboPooledDataSource();
- dataSource.setDriverClass(driver);
- dataSource.setJdbcUrl(url);
- dataSource.setUser(username);
- dataSource.setPassword(password);
- Connection connection=dataSource.getConnection();
- System.out.println(connection);
- connection.close();
- }
运行结果:

配置文件的好处有给程序解耦,打完包之后不会变化,程序打完包都是对应的字节码文件,而配置文件还是原模原样。
先在pom.xml导入spring的基本坐标
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-contextartifactId>
- <version>5.0.5.RELEASEversion>
- dependency>
在resource资源下创建ApplicationContext.xml
- "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">
-
-
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
-
- <property name="driverClass" value="com.mysql.jdbc.Driver">property>
- <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/kc_db01">property>
- <property name="user" value="root">property>
- <property name="password" value="123456">property>
- bean>
-
- beans>
在DataSourceTest类下
- @Test
- public void test4() throws Exception{
- ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
- // DataSource dataSource= (DataSource) app.getBean("dataSource");
- DataSource dataSource= app.getBean(DataSource.class);
- Connection connection=dataSource.getConnection();
- System.out.println(connection);
- connection.close();
- }
运行结果

applicationContext.xml加载jdbc.properties配置文件获得连接信息
首先,需要引入context命名空间和约束路径:
命名空间:
xmlns:context="http://www.springframework.org/schema/context"
约束路径:
- http://www.springframework.org/schema/context
-
- http://www.springframework.org/schema/context/spring-context.xsd
applicationContext.xml文件
- "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">
-
- <context:property-placeholder location="classpath:MyJdbc.properties"/>
-
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
-
- <property name="driverClass" value="${jdbc.driver}">property>
- <property name="jdbcUrl" value="${jdbc.url}">property>
- <property name="user" value="${jdbc.username}">property>
- <property name="password" value="${jdbc.password}">property>
-
- bean>
-
- beans>
MyJdbc.properties文件下
- jdbc.driver=com.mysql.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/kc_db01
- jdbc.username=root
- jdbc.password=123456
类中代码不变,运行结果为

Spring是轻代码而中配置,配置比较繁琐,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。
Spring原始注解主要是替代

注意:使用注解进行开发是,需要在applicationContext.xml中配置组件扫描,作用是值定哪个宝及其子包下的Bean需要进行扫描以便识别使用注解的类、字段个方法
在com包下创建Dao包,service包,web包
在Dao包下的UserDao接口
- public interface UserDao {
- public void save();
- }
在Dao包下的Impl包下的UserDaoImpl类
注解替换位置
- //
- @Component("userDao")
- //这个注解和上面xml一样
- package com.Dao.impl;
-
- import com.Dao.UserDao;
- import org.springframework.stereotype.Component;
-
- //
- @Component("userDao")
- //这个注解和上面xml一样
- public class UserDaoImpl implements UserDao {
- @Override
- public void save() {
- System.out.println("running...");
- }
- }
service包下的UserService接口
- public interface UserService {
- public void save();
- }
service包下的Impl包下的UserServiceImpl类
注解替换位置
- //
- @Component("userService")//这是一个组件,这个注解等于以上的xml配置
- //
- @Autowired // 这个表示自动注入
- @Qualifier("userDao")//里面写要注入的bean的id
- package com.service.Impl;
-
- import com.Dao.UserDao;
- import com.service.UserService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Qualifier;
- import org.springframework.stereotype.Component;
-
- //
- @Component("userService")//这是一个组件
- public class UserServiceImpl implements UserService {
-
- //
- @Autowired // 这个表示自动注入
- @Qualifier("userDao")//里面写要注入的bean的id
- private UserDao userDao;
- //使用注解可以不写set方法
- /* public void setUserDao(UserDao userDao) {
- this.userDao = userDao;
- }
- */
-
- @Override
- public void save() {
- userDao.save();
- }
- }
在web包下的UserController类下
- package com.web;
-
- import com.service.UserService;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class UserController {
- public static void main(String[] args) {
- ApplicationContext app=new ClassPathXmlApplicationContext("ApplicationContext.xml");
- UserService userService = app.getBean(UserService.class);
- userService.save();
- }
-
- }
运行结果

- @Component("userService")//这是一个组件
- public class UserServiceImpl implements UserService {
-
- //
- @Autowired // 按照数据类型从Spring容器中进行匹配的
-
- private UserDao userDao;
-
- @Override
- public void save() {
- userDao.save();
- }
- }
如果根据id进行匹配就要
- @Autowired // 按照数据类型从Spring容器中进行匹配的
- @Qualifier("userDao")//是按照id从容器中进行匹配的,但是主要此处的 @Qualifier结合@Autowired一起使用
@Resource(name ="userDao")//等价于 @Autowired +@Qualifier
- package com.service.Impl;
-
- import com.Dao.UserDao;
- import com.service.UserService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Qualifier;
- import org.springframework.stereotype.Component;
-
- import javax.annotation.Resource;
-
- //
- @Component("userService")//这是一个组件
- public class UserServiceImpl implements UserService {
-
- //
- // @Autowired // 按照数据类型从Spring容器中进行匹配的
- // @Qualifier("userDao")//是按照id从容器中进行匹配的,但是主要此处的 @Qualifier结合@Autowired一起使用
- @Resource(name ="userDao")//等价于 @Autowired +@Qualifier
- private UserDao userDao;
-
-
- @Override
- public void save() {
- userDao.save();
- }
- }
使用注解的方式set方法可以省略不写,使用想xml配置就必须写,注解是通过反射
@Value可以注入值,一般使用el表达式获取配置文件中的值
- @Value("${jdbc.driver}")
- private String user;

运行结果

也可以注入普通值,但是显示十分的多余,下面两种方式一样。
- @Value("hello")
- private String test;
-
-
- private String test="hello";
在serviceImpl中
- @PostConstruct
- public void init(){
- System.out.println("初始方法");
- }
- @PreDestroy
- public void destory(){
- System.out.println("销毁方法");
- }

使用上面的注解还不能 全部不代替xml配置文件,还需要使用注解替代的配置如下:
非自定义的Bean的配置:
加载properties文件的配置:
组件扫描的配置:
引入其他文件:
spring新注解

在config包下,创建名为DataSourceConfiguration类下
- package com.config;
-
-
- import com.mchange.v2.c3p0.ComboPooledDataSource;
- import org.springframework.beans.PropertyAccessException;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.PropertySource;
-
- import javax.sql.DataSource;
- import java.beans.PropertyVetoException;
-
- // 加载外部properties文件
- @PropertySource("classpath:MyJdbc.properties")
-
- public class DataSourceConfiguration {
- @Value("${jdbc.driver}")
- private String driver;
- @Value("${jdbc.url}")
- private String url;
- @Value("${jdbc.password}")
- private String password;
- @Value("${jdbc.username}")
- private String username;
-
- @Bean("dataSource")//Spring会将当前方法的返回值以指定名称存储到Spring容器中
- public DataSource getDateSource() throws PropertyAccessException, PropertyVetoException {
- ComboPooledDataSource dataSource=new ComboPooledDataSource();
- dataSource.setDriverClass(driver);
- dataSource.setJdbcUrl(url);
- dataSource.setPassword(password);
- dataSource.setUser(username);
- return dataSource;
- }
- }
在config包下创建SpringConfiguration类下
- package com.config;
-
- import com.mchange.v2.c3p0.ComboPooledDataSource;
- import org.springframework.beans.PropertyAccessException;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.*;
-
- import javax.sql.DataSource;
- import java.beans.PropertyVetoException;
-
- //标志该类是Spring的核心配置类
- @Configuration
-
- // base是基本包他会扫描其子类下的所有包
- @ComponentScan("com")
-
- //在总配置中加载分配置,加载核心配置类,若有多个,则写xx.class,xxx.class....
- @Import(DataSourceConfiguration.class)
- public class SpringConfiguration {
-
- }
web包下的UserController测试下
- package com.web;
-
- import com.config.SpringConfiguration;
- import com.service.UserService;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.annotation.AnnotationConfigApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class UserController {
- public static void main(String[] args) {
- //ApplicationContext app=new ClassPathXmlApplicationContext("ApplicationContext.xml");
- ApplicationContext app=new AnnotationConfigApplicationContext(SpringConfiguration.class);
- UserService userService = app.getBean(UserService.class);
- userService.save();
- }
-
- }
运行结果

原始Junit测试Spring的问题
在测试类中,每个测试方法都有一下两行代码:
- //获得应用上下文对象
- ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
-
- //获取要被测试的对象
- IAccountService as=ac.getBean("accountService",IAccountService.class);
这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常,所以又不能轻易删除。
解决思路
①导入spring集成Junit的坐标(首先导入好junit)
②使用@Runwith注解替换原来的运行期
③使用@ContextConfiguration指定配置文件或配置类
④使用@Autowired注入需要测试的对象
⑤创建测试方法进行测试
在pom.xml中导入
- <dependencies>
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-contextartifactId>
- <version>5.0.5.RELEASEversion>
- dependency>
-
-
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>4.12version>
-
- dependency>
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-testartifactId>
- <version>5.0.5.RELEASEversion>
- dependency>
-
- dependencies>
在test包下创建SpringJunitTest类
- package com.test;
-
- import com.service.UserService;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.test.context.ContextConfiguration;
- import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
- //指定Spring提供的内核去测试
- @RunWith(SpringJUnit4ClassRunner.class)
-
- //将要测试的文件告诉它
- @ContextConfiguration("classpath:ApplicationContext.xml")
- public class SpringJunitTest {
- @Autowired
- private UserService userService;
- @Test
- public void test1(){
- userService.save();
- }
- }
测试结果

在创建dao包,创建service包,创建web包,在resource资源
在创建一个UserDao和UserDaoImpl实现类
接口下
- package com.dao;
-
- public interface UserDao {
- public void save();
- }
实现类
- package com.dao.Impl;
-
- import com.dao.UserDao;
-
- public class UserDaoImpl implements UserDao {
- public void save() {
- System.out.println("save running...");
- }
- }
service包下,创建UserService和UserServiceImpl
接口
- package com.service;
-
- public interface UserService {
- public void save();
- }
实现类下
- package com.service.Impl;
-
- import com.dao.UserDao;
- import com.service.UserService;
-
- public class UserServiceImpl implements UserService {
-
- public UserDao userDao;
-
- public void setUserDao(UserDao userDao) {
- this.userDao = userDao;
- }
-
- public void save() {
- userDao.save();
- }
- }
pom.xml下
- <dependencies>
-
- <dependency>
-
-
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>4.11version>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-testartifactId>
- <version>5.0.5.RELEASEversion>
- dependency>
- <dependency>
- <groupId>javax.servlet.jspgroupId>
- <artifactId>javax.servlet.jsp-apiartifactId>
- <version>2.2.1version>
- <scope>providedscope>
- dependency>
-
- <dependency>
- <groupId>javax.servlet.jspgroupId>
- <artifactId>javax.servlet.jsp-apiartifactId>
- <version>2.2.1version>
- <scope>providedscope>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-contextartifactId>
- <version>5.3.0version>
- <scope>compilescope>
- dependency>
-
-
- dependencies>
resource资源路径下
applicationContext.xml下
- "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">
-
- <bean id="userDao" class="com.dao.Impl.UserDaoImpl">bean>
-
- <bean id="userService" class="com.service.Impl.UserServiceImpl">
- <property name="userDao" ref="userDao">property>
- bean>
-
- beans>
web包下,UserServlet类下,使用注解完成配置
- package com.web;
-
- import com.service.UserService;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
-
- //使用注解代替web.xml中的配置
- @WebServlet("/user")
- public class UserServlet extends HttpServlet {
- @Override
- protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- ApplicationContext app= new ClassPathXmlApplicationContext("applicationContext.xml");
- UserService userService = app.getBean(UserService.class);
- userService.save();
- System.out.println("jin");
-
- }
- }

首先这得是war包,如果这是普通包得添加webapp,并将pom.xml中加入如下,表示这是一个web文件
<packaging>warpackaging>

加完之后点击编辑配置

其下的war二选一即可

完成之后点击确认即可完成配置。
第一步,点击项目结构,选中 要添加的maven工程,右键添加web。

第二步,点击web工程,修改web工程路径

点击完成即可完成web工程的手动配置。
应用上下文对象是通过new ClasspathXmlApplicationContext(spring配置文件)方式获取的,但是每次从容器中获得Bean时都要编写new ClasspathXmlApplicationContext(spring配置文件),这样的弊端是配置文件加载多次,应用上下文对象创建多次。
在Web项目中,可以使用ServletContextListener监听Web应用的启动,我们可以在Web应用启动时,就加载Sprina的配置文件,创建应用上下文对象ApplicationContext,在将其存储到最大的域servletContext域中,这样就可以在任意位置从域中获得应用上下文ApplicationContext对象了。
新建一个Listenter包下的ContextLoderListener
- package com.Listener;
-
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- import javax.servlet.ServletContext;
- import javax.servlet.ServletContextEvent;
- import javax.servlet.ServletContextListener;
-
- public class ContextLoaderListener implements ServletContextListener {
- public void contextInitialized(ServletContextEvent servletContextEvent) {
- ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
- //将Spring的应用上下文对象存储到ServletContext域中
- ServletContext servletContext = servletContextEvent.getServletContext();
- servletContext.setAttribute("app", app);
- System.out.println("Spring容器创建完毕");
-
- }
- public void contextDestroyed(ServletContextEvent servletContextEvent) {
-
- }
- }
web包下
- package com.web;
-
- import com.service.*;
- import org.springframework.context.ApplicationContext;
-
- import javax.servlet.ServletContext;
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- @WebServlet("/user")
- public class UserServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- // ApplicationContext app= new ClassPathXmlApplicationContext("applicationContext.xml");
- ServletContext servletContext = req.getServletContext();
- ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
- UserService userService=app.getBean(UserService.class);
-
- }
- }
web.xml下配置监听器
- "1.0" encoding="UTF-8"?>
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- version="4.0">
-
- <listener>
- <listener-class>com.Listener.ContextLoaderListenerlistener-class>
- listener>
-
-
-
- web-app>
自动创建spring容器
解耦合1
由于监听器内部我们将代码写固定了,不利于后期的维护操作,所以要解耦合,写在配置文件中进行解耦合。(“”引号内的名字任意)
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
将此个代码写入到web.xml中进
- <context-param>
-
- <param-name>ContextConfigLocationparam-name>
- <param-value>applicationContext.xmlparam-value>
- context-param>
在ContextLoaderListenter类中
- package com.Listener;
-
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- import javax.servlet.ServletContext;
- import javax.servlet.ServletContextEvent;
- import javax.servlet.ServletContextListener;
-
- public class ContextLoaderListener implements ServletContextListener {
- public void contextInitialized(ServletContextEvent servletContextEvent) {
- ServletContext servletContext = servletContextEvent.getServletContext();
-
- //读取web.xml中的全局参数
- String contextConfigLocation = servletContext.getInitParameter("ContextConfigLocation");
- ApplicationContext app = new ClassPathXmlApplicationContext(contextConfigLocation);
- //将Spring的应用上下文对象存储到ServletContext域中
-
- servletContext.setAttribute("app", app);
- System.out.println("Spring容器创建完毕");
-
- }
-
- }
读取配置文件的值,这样就完成了解耦合
在userServlet类中
ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
这样耦合了app代码,让这个只能叫做app,这样不利于后期维护和辨认。
所以我们这么改,在Listener包下创建一个工具类WebApplicationContextUtils
- package com.Listener;
-
- import org.springframework.context.ApplicationContext;
-
- import javax.servlet.ServletContext;
-
- public class WebApplicationContextUtils {
- public static ApplicationContext getApplicationContext(ServletContext servletContext){
- return (ApplicationContext) servletContext.getAttribute("app");
- }
- }
在userServlet处代码修改为
- package com.web;
-
- import com.Listener.WebApplicationContextUtils;
- import com.service.*;
- import org.springframework.context.ApplicationContext;
-
- import javax.servlet.ServletContext;
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- @WebServlet("/user")
- public class UserServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- // ApplicationContext app= new ClassPathXmlApplicationContext("applicationContext.xml");
- ServletContext servletContext = req.getServletContext();
- //ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
- //变动处
- ApplicationContext app = WebApplicationContextUtils.getApplicationContext(servletContext);
- UserService userService=app.getBean(UserService.class);
-
- }
- }
上面写出的手动实现的监听器,Spring提供了一个监听器ContextLoderListener就是对上述功能的封装,该监听器内部加载Spring配置文件,创建应用上下文对象,并存储到ServletContext域中,提供一个客户亿工具WebApplicationContextUtils供使用者获得上下文对象
要使用监听器,需要做两件事:
①:在web.xml中配置ContextLoaderListener监听器(导入spring-web坐标)
②:使用WebApplicationContextUtils获得应用上下文对象 ApplicationContext
在pim.xml中导入坐标
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-webartifactId>
- <version>5.0.5.RELEASEversion>
- dependency>
web.xml中
-
- <context-param>
-
- <param-name>ContextConfigLocationparam-name>
- <param-value>classpath:applicationContext.xmlparam-value>
- context-param>
-
-
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
-
- listener>
userServlet类中,使用WebApplicationUtils获得上下文
-
- @WebServlet("/user")
- public class UserServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- // ApplicationContext app= new ClassPathXmlApplicationContext("applicationContext.xml");
- ServletContext servletContext = req.getServletContext();
- //ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
- //变动处
- //ApplicationContext app = WebApplicationContextUtils.getApplicationContext(servletContext);
- WebApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
- UserService userService=app.getBean(UserService.class);
-
- }
- }
这样就成功使用了spring给我们提供的监听器。
SpringMVC(M:Model模型,V:views视图,C:Controller控制器)是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于SpringFrameWork的后续产品,已经融合在Spring Web Flow中。
SpringMVC已经成为目前最主流的MVC框架之一,并且随着Spring3.0的发布,全面超越Struct2,成为最优秀的MVC框架,他通过一套注解,让一个简单的Java类成为处理请求的控制器,而无须实现任何接口,同时他还支持RESTful编程分格的请求

SpringMVC的核心是前端控制器,SpringMVC使用Servlet充当前端控制器
需求::客户端发起请求,服务器接受请求,执行逻辑并进行视图跳转。
1、先导入SpringMVC的相关坐标
2、配置SpringMVC核心控制器DispathcerServlet
3、创建Controller类和视图界面
4、使用注解配置Controller类中业务方法的映射地址
5、配置SpringMVC核心文件spring-mvc.xml
6、客户端发起请求测试
②、导入坐标
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-webmvcartifactId>
- <version>5.0.5.RELEASEversion>
- dependency>
②、配置控制器
- <servlet>
- <servlet-name>DispatcherServletservlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
- <load-on-startup>1load-on-startup>
- servlet>
- <servlet-mapping>
- <servlet-name>DispatcherServletservlet-name>
- <url-pattern>/url-pattern>
- servlet-mapping>
③、创建controller视图和视图界面④、使用注解映射地址
创建一个controller包,包下创建一个userController类,类中
- package com.controller;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
-
- //配置类,使用注解把这个类放到容器中
- @Controller
- public class userController {
-
- //用注解给这个方法请求映射某个地址
- @RequestMapping("/quick")
- public String save(){
- System.out.println("controller save running");
- //就会跳转到KCandZH.jsp这个页面上去
- return "KCandZH.jsp";
- }
- }
在webapp下创建一个KCandZH.jsp页面
- <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
- <%
- String path = request.getContextPath();
- String basepath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
- %>
- <head>
-
"<%=basepath %>"/> - "utf-8"/>
-
Insert title here - kCandZH forever