一.什么是spring?
Spring指的是Spring Framework,通常被我们叫做Spring框架.Spring是一个轻量化的,IOC和AOP的一站式java开发框架,是为了解决企业级引用开发的复杂性而创建的。
Spring有两个核心模块:IOC和AOP.
1.IOC(控制反转)
IOC:即 Inversion of Control,为控制反转.
传统开发中,需要调用对象的时候,需要调用者手动来创建被调用者的实例,即对象是由调用者new出来的,但是在Spring框架中,创建对象的工作不再由调用者来完成,而是交给IOC容器来创建,再推送给调用者,整个流程完成反转,所以是控制反转
1.1如何使用IOC
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
●创建实体类Admin
public class Admin {
private String account;
private String password;
public Admin() {
}
public Admin(String account, String password) {
this.account = account;
this.password = password;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Admin{" +
"account='" + account + '\'' +
", password='" + password + '\'' +
'}';
}
}
●编写spring配置文件
<?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="admin" class="com.ffyc.springpro.model.Admin"></beans>
</beans>
●传统开发
Admin admin=new Admin();
admin.setAccount("admin");
admin.setPassword("111")
System.out.println(admin);
●在spring框架中,创建对象的同时,还有一个动作被称为依赖注入.
依赖注入:在创建对象的时候,为对象中属性赋值
<bean id="admin" class="com.ffyc.springpro.model.Admin">
<constructor-arg name="account" value="admin"></constructor-arg>
<constructor-arg name="password" value="111"></constructor-arg>
</bean>
●IOC容器通过加载配置文件,读取bean标签来创建对象,通过调用API来获取对象
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
Admin admin=applicationContext.getBean("admin",Admin.class);
System.out.println(admin);
1.2bean标签
在spring的配置文件中注册需要spring框架管理的类时,需要使用bean标签进行配置.
<bean id="admin" class="com.ffyc.springpro.model.Admin" scope="prototype">
<property name="account" value="admin"></property>
<property name="password" value="111"></property>
</bean>
● id="对象名称",可以在getBean中获得spring生成的对象
● class=''需要让spring管理的类的地址"
● scope="配置bean的作用域
scope="singleton" 单例的(默认的) 在spring框架启动时,就创建对象,而且始终只创建一个对象
scope="prototype" 原型的(多例的) 在每次获得对象时,创建一个新的对象
● 成员变量通过<property>标签进行赋值
● name="成员变量名"
● value="给成员变量赋的值"
● ref="把IOC"中另一个bean赋给当前bean
1.3依赖注入
DI (Dependency Injection),依赖注入,依赖注入实现了控制反转的思想,是指Spring创建对象的过程中,将对象依赖属性通过配置进行注入。
依赖注入的两种方式:
1.通过属性注入(属性的set方法)
<bean id="admin" class="com.ffyc.springpro.model.Admin" scope="prototype">
<property name="account" value="admin"></property>
<property name="password" value="111"></property>
</bean>
2.通过构造方法注入
<bean id="admin" class="com.ffyc.springpro.model.Admin" >
<constructor-arg name="account" value="admin"></constructor-arg>
<constructor-arg name="password" value="111"></constructor-arg>
</bean>
Bean管理:指Bean对象的创建,以及Bean对象中属性的赋值(或Bean对象之间关系的维护)
1.4注解方式
首先要开启注解,在配置文件中添加
<context:component-scan base-package="包名"> </context:component-scan>
创建注解对象
@Component(value=“admin”)
@Service
@Repository
● 以上注解都可以实现创建对象功能,只是为了后续扩展功能,在不同的层使用不同的注解标记
@Autowired
● 1.通过属性的类型查找
该注解默认使用按类型自动装配Bean的方式。● 2.通过对象的名字查找
如果我们想使用按照名称(byName)来装配,可以结合@Qualifier注解一起使用。需要在引用属性上联合使用注解@Autowired与@Qualifier。@Qualifier的value属性用于指定要匹配的Bean的id值。
java也提供了注解标签@Resource
S pring提供了对jdk中@Resource注解的支持。@Resource注解既可以按名称匹配Bean,也可以按类型匹配Bean。默认按照ByName自动注入byName注入引用类型属性@Resource注解指定其name属性,则name的值即为按照名称进行匹配的Bean的id
注解与XML的对比
● 注解优点:方便,直观,高效(代码少,没有配置文件的书写那么复杂)
● 注解缺点:以硬编码的方式写入Java代码中,修改是需要重新编译代码的
● xml优点:配置和代码是分离的,在xml中做修改,无需编译代码,只需重启服务器即可将新的配置加载
● xml缺点:编写麻烦,效率低,大型项目过于复杂
2.AOP(面向切面编程)
AOP(AspectOrientedProgramming),面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术,是对面向对象编程的一种延续.
面向切面编程思想是将程序中的非业务代码(提交事务,打印日志,权限验证,统一异常处理)提取分离出来,然后在调用业务代码时,通过一个代理对象帮助我们调用这些提取出来的非业务代码,这样在业务代码不用显示的调用非业务代码,做到了业务代码和非业务代码的分离,降低了耦合度,同时提高了开发的效率
好处:减少重复,专注业务
核心原理:动态代理(给业务代码生成代理对象)
2.1AOP的基本概念
● 连接点(Joinpoint):类中可以被增强(加功能)的方法
● 切入点(pointcut):类中实际被增强的方法
● 目标(Target):代理的目标(连接点和切入点所在的类)
● 代理(Prox):向目标对象,应用通知时创建的代理对象
● 通知(Advice):指一个切面特定的连接点要做的事情(增强的功能)
2.2AOP的实现
对于AOP这种编程思想,很多框架都进行了实现。Spring就是其中之一,可以完成面向切面编程。AspectJ是一个基于Java语言的AOP框架,它提供了强大的AOP功能,且其实现方式更为简捷,使用更为方便,而且还支持注解式开发。所以,Spring又将AspectJ的对于AOP的实现也引入到了自己的框架中。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
2.3AspectJ常用的通知类型
AspectJ有五种常用的通知类型:
@Before():前置通知 在业务方法执行前调用执行
@Before("execution(* com.ffyc.springpro.dao.AdminDao.*(..))")
public void printLog(){
System.out.println("打印日志");
}
@After():后置通知 在方法执行完后调用执行 当业务代码中出现异常,也会执行
@After("execution(* com.ffyc.springpro.dao.AdminDao.*(..))")
public void printLog(){
System.out.println("提交事务");
}
@AfterReturning():返回执行 在业务执行完后调用执行 当业务代码中出现异常,不会执行
@AfterReturning("execution(* com.ffyc.springpro.dao.AdminDao.*(..))")
public void commit(){
System.out.println("提交事务");
}
@AfterThrowing():异常通知 当业务代码出现异常时执行
@AfterThrowing(value = "execution(* com.ffyc.springpro.dao.AdminDao.*(..))",throwing = "e")
public void exception(Throwable e){
System.out.println("系统忙"+e.getMessage());
e.printStackTrace();
}
@Around():环绕通知 方法执行前后都有通知
public void around(ProceedingJoinPoint joinPoint){
System.out.println("前置通知");
try {
Object[]objects=joinPoint.getArgs();//获取到我们目标方法的参数
System.out.println(Arrays.toString(objects));
joinPoint.proceed();//调用目标业务方法
System.out.println("返回通知");
} catch (Throwable e) {
e.printStackTrace();
System.out.println("异常通知");
}
System.out.println("后置通知");
}
2.4事务管理
● 数据库事务管理:对一次数据库操作过程中执行多条语句进行管理,保证一次对数据库操作过程中多条sql要么都执行成功,要么都不执行,从而确保数据的一致性.
● 作用:为了保证用户的每一个操作都是可靠的,事务中的每一步操作都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态,这些操作要么都完成,要么都取消,从而保证数据满足一致性的要求.
● spring事务管理:spring框架针对程序中提交事务这部分非业务代码进行分离管理,减轻程序员负担.在程序执行没有问题时,提交事务,出现问题时,回滚事务
事务管理的形式
spring中的事务管理分为两种形式:
1.编程式事务:这种方式需要我们在代码中需要提交事务或回滚事务时自己写代码实现
2.声明式事务:建立在AOP基础上,本质是对方法前后进行拦截,所以声明式事务是方法级别的.
spring事务的实现
Spring框架基于注解实现的事务管理,它提供事务管理实现类是是 DataSourceTransactionManager.
● 在配置文件中配置事务管理器
<!-- 配置 spring 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
● 在配置文件中开启注解事务管理
<!-- 开启注解事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
● 在类或方法上使用@Transactional 标签即可
@Transactional
public class AdminService {
}
声明式事务的失败场景
1.@Transactional使用在非public方法上面
2.方法的异常被捕获,认为方法没有异常
一般不将其放在方法上,会直接将标签放到Service类上
3.方法中出现编译期异常,还是会提交事务
一般将标签写为@Transactional(rollbackFor = Exception.class)
4.数据库引擎不支持事务(MySQL中只有innodb引擎支持事务)
3.spring数据访问层管理
3.1spring JDBC
● 导入jar包
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!-- 阿里数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
● 在配置文件中导入属性文件
<context:property-placeholder location="config.properties"/>
● 基于IOC将数据库链接对象交给spring管理(采用阿里巴巴数据库链接管理对象)
<bean id="dataSource"class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value=""></property>
<property name="url" value=""></property>
<property name="username" value=""></property>
<property name="password" value=""></property>
<property name="initialSize" value="10"></property><!--初始化连接数量-->
<property name="maxActive" value="20"></property><!--最大连接数量-->
</bean>
通过IOC注解创建JdbcTemplate对象,调用sql语句进行查询
@Repository(value = "adminDao")
public class AdminDao {
@Autowired
JdbcTemplate jdbcTemplate;
public void saveAdmin(){
//jdbcTemplate.update("insert into admin(account,password,gender)values (?,?,?)","zhang","123","男");
List<Admin>adminList=jdbcTemplate.query("select * from admin", new RowMapper<Admin>() {
@Override
public Admin mapRow(ResultSet resultSet, int i) throws SQLException {
Admin admin=new Admin();
admin.setAccount(resultSet.getString("account"));
admin.setPassword(resultSet.getString("password"));
return admin;
}
});
System.out.println(adminList);
}
}
3.2spring mybatis
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
● 配置sqlSessionFactory
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath:mappers/*Mapper.xml">
</property>
</bean>
● 指定生成代理接口
<bean id="mapperFactory" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ffyc.ssm.dao"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory">
</property>
</bean>
● 在service中注入Dao代理接口,此接口有Spring代理实现
@Autowired
AdminDao adminDao;