Maven项目的创建
项目所在路径
- 项目一
- 创建Module
- 添加Webapp(Project Structure)
- 项目二
Spring简介
分层全栈(各层解决方案)轻量级框架,以IoC和AOP为内核
Spring优势
- 方便解耦,简化开发
- AOP编程的支持
- 声明式事务的支持
- 方便程序的测试
- 方便集成各种优秀的框架
- 降低JavaEE API的使用难度
Spring开发步骤
-
导入spring坐标
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.20</version> </dependency>
-
创建DAO接口
dao.UserDao
package com.miaokela.dao; public interface UserDao { public void save(); }
-
创建Dao接口实现类
dao.Impl.UserDaoImpl
package com.miaokela.dao.impl; import com.miaokela.dao.UserDao; public class UserDaoImpl implements UserDao { public void save(){ System.out.println("save running..."); } }
-
创建Spring配置文件
resources.applicationContext
<?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"> <bean id="userDao" class="com.miaokela.dao.impl.UserDaoImpl"></bean> </beans>
-
从容器中获取实现类对象
demo.UserDaoDemo
package com.miaokela.demo; import com.miaokela.dao.UserDao; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; 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标签的基本配置
-
基本属性
默认情况下调用的是类中的无参构造函数 id: 容器唯一标识 class: Bean标签的基本配置全限定名
-
范围配置
scope 对象作用范围 - singleton 默认值,单例的 - prototype 多例的 - request request域 - session session域 - global session 全局session域
-
Bean创建时间与销毁时间
- singleton
加载配置文件时创建
容器在,对象在
销毁容器时,对象销毁 - prototype
getBean的时候创建
对象一直使用中存在
对象长时间不用,被垃圾回收
- singleton
-
-
Bean的生命周期
- init-method
指定类中初始化方法名称
- destroy-method
指定类中销毁方法名称
自定义实现方法
package com.miaokela.dao.impl; import com.miaokela.dao.UserDao; public class UserDaoImpl implements UserDao { public void save() { System.out.println("save running..."); } public void init() { System.out.println("初始化方法"); } public void destroy() { System.out.println("销毁方法"); } }
绑定实现方法
<?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"> <bean id="userDao" class="com.miaokela.dao.impl.UserDaoImpl" init-method="init" destroy-method="destroy"></bean> </beans>
- init-method
-
Bean实例化的三种方式
-
无参构造
-
工厂静态方法
需要配置 factory-method
-
工厂实例方法
需要配置 factory-bean、factory-method
-
依赖注入
通过控制反转,把对象的创建给Spring,降低依赖关系,通过Spring来维护业务层和持久层的依赖关系
-
业务流程
UserDao -> UserService -> UserController
-
依赖注入方法
-
set方法
service.impl.UserServiceImpl
package com.miaokela.service.impl; import com.miaokela.dao.UserDao; import com.miaokela.service.UserService; public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void save() { // ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); // UserDao userDao = (UserDao) app.getBean("userDao"); userDao.save(); } }
applicationContext.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"> <bean id="userDao" class="com.miaokela.dao.impl.UserDaoImpl"></bean> <bean id="userService" class="com.miaokela.service.impl.UserServiceImpl"> <property name="userDao" ref="userDao"></property> </bean> </beans>
demo.UserController
可以使用p命名空间注入package com.miaokela.demo; import com.miaokela.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.impl.UserServiceImpl
package com.miaokela.service.impl; import com.miaokela.dao.UserDao; import com.miaokela.service.UserService; public class UserServiceImpl implements UserService { private UserDao userDao; // public void setUserDao(UserDao userDao) { // this.userDao = userDao; // } public UserServiceImpl(UserDao userDao) { this.userDao = userDao; } public void save() { // ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); // UserDao userDao = (UserDao) app.getBean("userDao"); userDao.save(); } }
applicationContext
<?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"> <bean id="userDao" class="com.miaokela.dao.impl.UserDaoImpl"></bean> <bean id="userService" class="com.miaokela.service.impl.UserServiceImpl"> <!-- <property name="userDao" ref="userDao"></property>--> <constructor-arg name="userDao" ref="userDao"></constructor-arg> </bean> </beans>
demo.UserController
package com.miaokela.demo; import com.miaokela.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(); } }
-
-
依赖注入的三种数据类型
-
普通数据类型
applicationContext
<bean id="userService" class="com.miaokela.service.impl.UserServiceImpl"> <property name="username" value="zhangsan"/></properties> <property name="age" value="20"/></properties> </bean>
-
引用数据类型
前面的注入方式
-
集合数据类型
数据模型
public class User { private String name; private String addr; // Getter/Setter // toString() }
实现类
private List<String> strList; private Map<String, User> userMap; private Properties properties; // setter
applicationContext
<bean id="userDao" class="com.miaokela.service.impl.UserDaoImpl"> <property name="strList"/> <list> <value>1</value> <value>2</value> <value>3</value> </list> </property> <property name="strList"/> <map> <entry key="u1" value-ref="user1"></entry> <entry key="u2" value-ref="user2"></entry> </map> </property> <property name="properties"/> <props> <prop key="p1">ppp1</entry> <prop key="p2">ppp2</entry> </props> </property> </bean> <bean id="user1" class="com.miaokela.domain.User"> <property name="name" value="zhangsan"/></properties> <property name="addr" value="shanghai"/></properties> </bean> <bean id="user2" class="com.miaokela.domain.User"> <property name="name" value="lisi"/></properties> <property name="addr" value="shanghai"/></properties> </bean>
-
分模块开发
引入其他配置文件
<import resource="applicationContext-xxx.xml"/>
Spring相关Api
- ApplicationContext继承体系
FileSystemXmlApplicationContext ClassPathXmlApplicationContext AnnotationConfigApplicationContext
- getBean()方法的使用
String id的方式 Class<T> requiredType 字节码类型的方式(UserService.class)
Spring配置数据源
-
连接池的作用
1.提高程序性能 2.实现初始化部分连接资源 3.从数据源中获取连接资源 4.使用后归回连接资源
-
常见数据源
DBCP C3P0 BoneCP Druid
-
开发步骤
-
导入坐标
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.4</version> </dependency>
-
测试数据源
test.java.com.miaokela.DataSourceTest
c3p0package com.miaokela; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.testng.annotations.Test; import java.beans.PropertyVetoException; import java.sql.Connection; import java.sql.SQLException; public class DataSourceTest { @Test public void test1() throws PropertyVetoException, SQLException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); dataSource.setUser("root"); dataSource.setPassword("123456"); Connection connection = dataSource.getConnection(); System.out.println(connection); connection.close(); } }
druid
package com.miaokela; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidPooledConnection; import org.testng.annotations.Test; import java.sql.SQLException; public class DataSourceTest { @Test public void test2() throws SQLException { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/test"); dataSource.setUsername("root"); dataSource.setPassword("123456"); DruidPooledConnection connection = dataSource.getConnection(); System.out.println(connection); connection.close(); } }
-
-
配置数据源文件
resource.jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/test jdbc.username=root jdbc.password=123456
读取配置文件 连接
package com.miaokela; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.testng.annotations.Test; import java.sql.Connection; import java.util.ResourceBundle; public class DataSourceTest { @Test public void test2() throws Exception { // 读取配置文件 ResourceBundle rb = ResourceBundle.getBundle("jdbc"); // 不需要扩展名 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(); } }
-
通过Spring配置数据源
将DataSource的创建权由Spring容器去完成
applicationContext
先引入context命名空间,再引入properties<?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"> <context:property-placeholder location="classpath:jdbc.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>
DataSourceTest
package com.miaokela; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.testng.annotations.Test; import javax.sql.DataSource; import java.sql.Connection; public class DataSourceTest { @Test public void test1() throws Exception { // 从容器对象中导入配置 ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); DataSource dataSource = app.getBean(DataSource.class); Connection connection = dataSource.getConnection(); System.out.println(connection); connection.close(); } }
Spring注解开发
- 原始注解
@Compoment
@Controller
@Service
@Repository
@Autowired
@Qualifier
@Resource
@value
@Scope
@PostContruct
@PreDestroy
-
注解替代xml的Bean标签
-
Bean的创建与注入
dao.impl.UserDaoImpl
@Compoment("userDao") public class UserDaoImpl implements UserDao { pubic void save() { System.out.println("save running...") } }
dao.service.impl.UserServiceImpl
public class UserServiceImpl implements UserService { // @Autowired // 注入 单独使用时,从Spring容器中进行匹配 // @Qualifier("userDao") // Bean id @Resource(name="userDao") // 根据名称注入,相当于Autowired+Qualifier private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } }
-
配置组件扫描
<context:compoment-scan base-backage="com.miaokela"/>
-
-
衍生注解
Controller web层 Service service层 Repository dao层
-
普通类型的注入
@Value("${jdbc.driver}") private String driver
-
单独设置单例模式
@Service("userService") @Scope("singleton") public class UserServiceImpl implements UserService { @Value("${jdbc.driver}") private String driver; }
-
Spring新注解
旧的不能替代xml的注解
1.非自定义的Bean配置 <bean></bean> 2.加载properties文件配置 <context:property-placeholder></context:property-placeholder> 3.组件扫描位置 <context:compoment-scan></context:compoment-scan> 4.引入其他文件 <import>
- 新注解
@Configuration // 配置容器时加载配置 @ComponentScan // Spring初始化容器扫描的包 @Bean // 存储容器 @PropertySource // 加载properties文件 @Import // 导入其他配置
- 新注解
-
Spring配置
解决不能替代xml注解的问题
config.SpringConfiguration@Configuration @ComponentScan("com.miaokela") // 3.组件扫描 @Import({DataSourceConfiguration.class}) // 4.import分模块 public class SpringConfiguration { }
config.DataSourceConfiguration
@PropertySource("classpath:jdbc.properties") // 2.加载properties文件 public class SpringConfiguration { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Bean("dataSource") // 1.非自定义的Bean Spring会将当前方法的返回值以指定名称存储到Spring容器中 public DataSource getDataSource() { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(driver); dataSource.setJdbcUrl(url); dataSource.setUser(username); dataSource.setPassword(password); return dataSource } }
测试
public class DataSourceTest { @Test public void test1() throws Exception { // 从容器对象中导入配置 ApplicationContext app = new AnnotationConfigApplicationContext("SpringConfiguration.class"); UserService userService = app.getBean(UserService.class); userService.save(); } }
-
Spring整合Junit
让SpringJunit负责创建Spring容器,需要将配置文件名称告诉它 注入需要测试的Bean
步骤
1.导入Spring继承Junit坐标 2.使用@Runwith注解替换原来的运行期 3.使用@ContextConfiguration之顶不过配置文件或配置类 4.使用@Autowire注入需要测试的对象 5.创建测试方法进行测试
-
导入坐标
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.3.20</version> </dependency>
-
实现整合
需要测试什么 直接注入
package com.miaokela; import com.miaokela.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; import javax.activation.DataSource; @RunWith(SpringJUnit4ClassRunner.class) //@ContextConfiguration("classpath:applicationContext.xml") // 配置文件方式 @ContextConfiguration(classes={SpringConfiguration.class}) // 注解方式 public class SpringJunitTest { @Autowired private UserService userService; @Autowired private DataSource dataSource; @Test public void test1() throws Exception { userService.save(); System.out.println(dataSource.getConnection()); } }
-