目录
Spring框架的概述
Spring的核心是控制反转(IoC控制反转)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架。
Spring框架的优点
1.方便解耦,简化开发,Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理。IOC的作用。
2.AOP编程的支持,Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。(可扩展性)
3.声明式事务的支持,只需要通过配置就可以完成对事务的管理,而无需手动编程。
4.方便程序的测试,Spring对Junit4支持,可以通过注解方便的测试Spring程序。
5.方便集成各种优秀框架,Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts2、Hibernate、MyBatis、Quartz等)的直接支持。
6.降低JavaEE API的使用难度,Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。
Spring的IOC核心技术
IOC -- Inverse of Control,控制反转,将对象的创建权力反转给Spring框架!!也就是在使用对象前不用再使用“new”来创建一个对象。
使用IOC可以解决的程序耦合性高的问题。就像去买东西,假设你需要去服装店买衣服,去鞋店买鞋,你需要去两次,但现在有一家店,这家店衣服和鞋都有,你只需要去这一家店就够了。之前新建不同对象需要不同的“new”出来,现在只需要使用spring工厂的getBean一个方法就够了。
IOC的入门程序
导入依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
编写接口与实现类
public interface UserService {
public void hello();
}
public class UserServiceImpl implements UserService {
@Override
public void hello() {
System.out.println("Hello IOC!!");
}
}
编写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">
<!--IOC管理bean-->
<bean id="userService" class="com.qcbyjy.service.UserServiceImpl" />
</beans>
class是你要交给spring管理的类路径;
还有一些其他属性,scope:singleton(单例模式)同容器工厂关闭时销毁 prototype(多例模式)
根据垃圾回收机制来回收;
init-method,当bean被载入到容器的时候调用
destroy-method,当bean从容器中删除的时候调用
实例化对象的三种方法:无参数的构造方法(用的最多)、静态工厂实例化、动态工厂实例化
编写测试方法
public class Demo1 {
/**
* 入门程序
*/
@Test
public void run1(){
// 使用Spring的工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过工厂获得类:
UserService userService = (UserService) applicationContext.getBean("userService");
userService.hello();
}
}
DI注入
构建实体类
public class car {
private int[] name;
public int[] getName() {
return name;
}
public void setName(int[] name) {
this.name = name;
}
public car() {
}
public car(int[] name) {
this.name = name;
}
@Override
public String toString() {
return "car{" +
"name=" + Arrays.toString(name) +
'}';
}
}
编写配置文件
使用set方法
<bean id="car" class="com.qcby.service.car">
<property name="name" value="奔驰"/>
</bean>
使用构造器
<bean id="car" class="com.qcby.service.car">
<constructor-arg name="name" value="奔驰"/>
</bean>
使用上述方法需要有对应的set方法或构造方法
若注入的属性不是基本类型时需要使用“ref”来替换掉value,同样这个类也需要交给spring来管理。
数组,集合和Properties的注入
实体类
public class CollectionBean {
// 数组
private String [] strs;
public void setStrs(String[] strs) {
this.strs = strs;
}
private List<String> list;
public void setList(List<String> list) {
this.list = list;
}
private Map<String,String> map;
public void setMap(Map<String, String> map) {
this.map = map;
}
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "CollectionBean{" +
"strs=" + Arrays.toString(strs) +
", list=" + list +
", map=" + map +
", properties=" + properties +
'}';
}
}
xml配置文件
<!--给集合属性注入值-->
<bean id="collectionBean" class="com.qcby.demo3.CollectionBean">
<property name="strs">
<array>
<value>美美</value>
<value>小凤</value>
</array>
</property>
<property name="list">
<list>
<value>熊大</value>
<value>熊二</value>
</list>
</property>
<property name="map">
<map>
<entry key="aaa" value="老王"/>
<entry key="bbb" value="小王"/>
</map>
</property>
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
多配置文件
如果有两个或者多个配置文件,有如下两种方式来加载
主配置文件中包含其他的配置文件:
<import resource="applicationContext2.xml"/>
工厂创建的时候直接加载多个配置文件:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml","applicationContext2.xml");
Spring框架开发方式
- 需求:编写service和dao的类,演示代码
- 技术选择:持久层使用原始的JDBC的程序,连接池选择的是Druid连接池。
创建maven工程,导入开发的jar包
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
创建数据库,创建表结构
create database spring_db;
use spring_db;
create table account(
id int primary key auto_increment,
name varchar(40),
money double
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
编写JavaBean的类
public class Account implements Serializable {
private static final long serialVersionUID = 7355810572012650248L;
private Integer id;
private String name;
private Double money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
编写AccountDao的接口和实现类
public interface AccountDao {
public List<Account> findAll();
}
public class AccountDaoImpl implements AccountDao {
// 注入连接池对象
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 查询所有的数据
* @return
*/
@Override
public List<Account> findAll() {
/*
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring_db");
dataSource.setUsername("root");
dataSource.setPassword("root");
*/
List<Account> list = new ArrayList<>();
Connection connection = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 获取连接
connection = dataSource.getConnection();
// 编写sql语句
String sql = "select * from account";
// 预编译
stmt = connection.prepareStatement(sql);
// 查询
rs = stmt.executeQuery();
// 遍历,封装数据
while (rs.next()){
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
list.add(account);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
}
编写AccountService的接口和实现类
public interface AccountService {
public List<Account> findAll();
}
public class AccountServiceImpl implements AccountService {
// 依赖注入
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
/**
* 查询所有的数据
* @return
*/
@Override
public List<Account> findAll() {
return accountDao.findAll();
}
}
编写配置文件
<?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="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///spring_db" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!--管理bean-->
<bean id="accountService" class="com.qcbyjy.service.AccountServiceImpl">
<property name="accountDao" ref="accountDao" />
</bean>
<bean id="accountDao" class="com.qcbyjy.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
编程测试程序
public class Demo1 {
@Test
public void run1(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService = (AccountService) ac.getBean("accountService");
// 调用方法
List<Account> list = accountService.findAll();
for (Account account : list) {
System.out.println(account);
}
}
}
IOC注解的方式
半注解
类中标注
@Component普通类通用
@Controller表现层
@Service业务层
@Repository持久
若()中value没有明确给出,则默认为首字母小写的类名,即UserService为userService。
编写配置文件
<!--开启注解扫描 com.qcbyjy.所有的包中的所有的类 -->
<context:component-scan base-package="com.qcby" />
依赖注入常用的注解
@Value 用于注入普通类型(String,int,double等类型)
@Autowired 默认按类型进行自动装配(引用类型)
@Qualifier 和@Autowired一起使用,强制使用名称注入
@Resource Java提供的注解,也被支持。使用name属性,按名称注入对象生命周期(作用范围)
@Scope 生命周期注解,取值singleton(默认值,单实例)和prototype(多例)
初始化方法和销毁方法注解(了解)
@PostConstruct 相当于init-method
@PreDestroy 相当于destroy-method
例子
@Component(value="person")
public class person {
@Value("塞恩")
private String name;
@Value("22")
private Integer age;
@Autowired
@Qualifier("wife02")
//@Resource(name = "wife02")
public wife wife;
@PostConstruct
public void init(){
System.out.println("操作...");
}
public person() {
}
public person(String name, Integer age,wife wife) {
this.name = name;
this.age = age;
this.wife = wife;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public wife getW() {
return wife;
}
public void setW(wife w) {
this.wife = w;
}
@Override
public String toString() {
return "person{" +
"name='" + name + '\'' +
", age=" + age +
", wife=" + wife +
'}';
}
}
测试
需要使用@ContextConfiguration来加载配置文件。
@ContextConfiguration(classes = "classpath:applicationContext.xml") //加载配置文件
public class demo1 {
@Autowired
private AccountService accountService;
@Test
public void run(){
List<account> list = accountService.findAll();
for (account account0 : list) {
System.out.println(account0);
}
}
}
纯注解
纯注解模式就是去掉配置文件,只用注解来完成,虽然不用配置文件,但是需要编写一个配置类。
@Configuration 声明是配置类
@ComponentScan 扫描具体包结构的
@Import注解 Spring的配置文件可以分成多个配置的,编写多个配置类。用于导入其他配置类
@Bean注解 只能写在方法上,表明使用此方法创建一个对象,对象创建完成保存到IOC容器中
// 声明当前类是配置类
@Configuration
// 扫描指定的包结构
@ComponentScan(value = "com.qcby.demo4")
// @ComponentScan(value = {"com.qcby.demo4","com.qcby.demo3"})
// 引入新的配置类
@Import(value = {SpringConfig2.class})
public class SpringConfig {
/**
* 创建连接池对象,返回对象,把该方法创建后的对象存入到连接池中,使用@Bean注解解决
*/
@Bean(name="dataSource")
public DataSource createDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring_db");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
}
测试
需要使用需要使用@ContextConfiguration来加载配置文件。
@ContextConfiguration(classes = SpringConfig.class) //加载配置类
public class demo1 {
@Autowired
private AccountService accountService;
@Test
public void run(){
List<account> list = accountService.findAll();
for (account account0 : list) {
System.out.println(account0);
}
}
}
Spring框架整合JUnit单元测试
每次进行单元测试的时候,都需要编写创建工厂,加载配置文件等代码,比较繁琐。Spring提供了整合Junit单元测试的技术,可以简化测试开发。
导入依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
<scope>test</scope>
</dependency>
测试
@RunWith(value = SpringJUnit4ClassRunner.class)声明为测试单元
@RunWith(value = SpringJUnit4ClassRunner.class)---加入测试单元
//ContextConfiguration(classes = "classpath:applicationContext.xml") //加载配置文件
@ContextConfiguration(classes = SpringConfig.class) //加载配置类
public class demo1 {
@Autowired
private AccountService accountService;
@Test
public void run(){
List<account> list = accountService.findAll();
for (account account0 : list) {
System.out.println(account0);
}
}
}