- **IOC**
- **AOP**
- aspectJ
- 使用xml的配置文件
- JoinPoint业务方法
- 后置通知AfterReturning
- 环绕通知
- 异常通知
- 最终通知After
- PointCut
- Spring集成MyBatis
- 回顾用Mybatis访问数据库
- Spring集成MyBatis步骤
- **加入各种依赖**
- **创建各种类和接口**
- **创建实体类**
- **创建dao接口和mapper文件**
- 创建mybatis主配置文件
- **创建Spring的配置文件**
- Spring开启事务
动态代理 做了一个 标准化。
Spring 内部实现了AOP规范
Spring 主要在事务处理时使用AOP
项目中 很少使用Spring中的AOP实现 因为其 比较笨重
aspectJ一般使用aspectJ :一个专门做AOP的框架
Spring 框架集成了aspectJ框架,所以 可以通过Spring使用aspectJ的功能
aspectJ框架实现AOP的两种方式
配置全局事务
切面执行时间
也可以使用xml中的标签来表示执行的时间
aspectJ实现步骤
01加依赖
org.springframework spring-aspects 5.2.17.RELEASE
注:这里添加的时候老是爆红,无论是刷新还是下载相对应依赖(在 idea里操作)都无效,然后将5.2.5改成5.2.17就好了 .17也是它自己提示才得到
02创建目标类接口
public interface SomeService {
void dosome(String name,Integer age);
}
03实现目标类
public class SomeServiceImpl implements SomeService {
@Override
public void dosome(String name,Integer age) {
System.out.println("******执行dosome******");
}
}
04创建一个切面类,切面类可以表示获取时间或日志等增强操作
@Aspect在方法上面表示注解类
@Before 在方法名上面表示前置通知注解
特点:在目标方法执行之前执行 不会改变目标方法的执行结果 不影响目标方法
@Aspect
public class Myaspect01 {
@Before(value = "execution(void com.hdu.ba01.SomeServiceImpl.dosome(String,Integer))")//位置+时间
public void myBefore(){
System.out.println("1前置通知 切面功能:在目标方法之前 输出执行时间:"+new Date());
}
@Before(value = "execution(void *..SomeServiceImpl.do*(String,Integer))")//位置+时间
public void myBefore2(){
System.out.println("2前置通知 切面功能:在目标方法之前 输出执行时间:"+new Date());
}
@Before(value = "execution(void *..SomeServiceImpl.do*(..))")//位置+时间
public void myBefore3(){
System.out.println("3前置通知 切面功能:在目标方法之前 输出执行时间:"+new Date());
}
}
//public 可省略 包名可以用 *..表示 //方法名后面可以用(..)代替(String,Integer) //甚至方法名那 都可以以某个开始的字符 来替换dosome --->do* //通知可以执行多个 如果参数 那写错了 或者少写 就加不进去 具体如上面表示。
05xml配置文件
06测试类
package com.hdu;
import com.hdu.ba01.SomeService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest01 {
@Test
public void test01(){
String config="applicationContext.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(config);
//从容器中获取目标对象
SomeService someService=(SomeService) applicationContext.getBean("SomeServiceImpl");
//执行目标方法
someService.dosome("lisi",24);
}
}
AOP作用
1在目标类不修改的源代码的情况下 增加功能
2减少重复代码
3专注业务功能的实现
4解耦合:业务功能和日志,事务这些非业务功能点额 耦合。
如何给指定多个目标类添加功能
@Before(valuess="execution(*com.hdu.ba01.*ServiceImp.*(..)")
这样指定某个包下的 ServiceImp 所有方法都可已添加功能。
JoinPoint业务方法切面功能要用到目标类方法的信息,就 加入JoinPoint
@Before(value = "execution(void com.hdu.ba01.SomeServiceImpl.dosome(String,Integer))")//位置+时间
public void myBefore(JoinPoint jp){
//获取方法的完整定义:
System.out.println("方法的签名(定义)"+jp.getSignature());
System.out.println("方法名"+jp.getSignature().getName());
//System.out.println(""+jp.getSignature().getModifiers());
System.out.println("获取方法的定义1前置通知 切面功能:在目标方法之前 输出执行时间:"+new Date());
}
后置通知AfterReturning
后置通知对目标方法返回值进行修改,并不会改变目标方法的返回值,因为这里的参数传递是值传递
可以对目标方法的返回值进行后续操作。
有固定参数ProceedingJoinPoint 能修改目标方法返回结果,影响最后结果
ProceedingJoinPoint继承于JoinPoint
定义格式
特点
结果
那么如何根据目标方法的返回值来控制目标方法
ProceedingJoinPoint pip
{ String name="";
Object args[]=pip.getArgs();//获取参数
if(args!=null&&args.length>=1){//说明有参数
Object arg=args[0]
name=(String)arg;
}
//然后根据参数 来判断 目标方法中的传参是否符合要求
if("zhangsan".equals(name)){
result=pip.proceed();
}
}
ProceedingJoinPoint继承于JoinPoint,其可以获取目标方法参数
然后在环绕通知内部 定义一个已知参数 与目标参数进行比较 从而来控制目标方法的进行
修改目标方法的结果,会影响最后的结果
为什么呢? 因为后面目标方法的调用被换成了环绕通知的的类,也就返回环绕通知的结果
给目标类起别名
01——pom.xml加入mybatis配置文件
org.mybatis
mybatis
3.5.2
mysql
mysql-connector-java
8.0.26
runtime
src/main/java
***.xml
false
02建立一个对象类
03——建立Dao接口
public interface StudentDao {
List selectStudent();
}
04——Dao包下的接口配置文件,用来写sql语句
05——mybatis配置文件,用来连接数据库的配置文件
06访问数据库执行sql语句
使用mybatis的动态代理,使用sqlSession.getMapper(dao接口)
这样就不用去写一个接口实现类,即不用每次都new一个对象 我们只需修改sql语句
package com.hau.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class MybatisUtil {
private static SqlSessionFactory factory=null;
static {
String config="mybatis.xml";
try {
InputStream in= Resources.getResourceAsStream(config);
factory=new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSesion(){
SqlSession sqlSession=null;
if (factory!=null){
sqlSession=factory.openSession();
}
return sqlSession;
}
}
写一个Test来进行测试,调用mybatis的动态代理
package com.hau;
import com.hau.dao.StudentDao;
import com.hau.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
public class TestMybtis {
@Test
public void testSelectStudent(){
SqlSession sqlSession= MybatisUtil.getSqlSesion();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
dao.selectStudent();
}
}
Spring集成MyBatis步骤
Spring和mybatis的集成步骤;
1.新建maven项目
2.加入maven的依赖
1)spring依赖
2)mybatis依赖
3)mysql驱动
4)spring的事物依赖
5)mybatis和spring的集成依赖:mybatis官方提供的,用来在spring项目中创建mybatis的SqlSessionFactory ,dao对象
3.创建实体类
4.创建dao接口和mapper文件
5.创建mybatis主配置文件
6.创建Service接口和实现类,属性是dao
7.创建spring的配置文件 :声明mybatis的对戏交给spring创建
1)数据源DataSource——durid
2)SQLSessionFactory
3)dao对象
4)声明自定义的service
8.创建测试类 完成数据库的访问
加入各种依赖junit junit 4.11 test org.springframework spring-context 5.2.5.RELEASE org.springframework spring-tx 5.2.5.RELEASE org.springframework spring-jdbc 4.3.17.RELEASE org.mybatis mybatis 3.5.2 org.mybatis mybatis-spring 2.0.5 mysql mysql-connector-java 8.0.26 runtime com.alibaba druid 1.1.7
build部分
创建各种类和接口 创建实体类 创建dao接口和mapper文件src/main/java **/ *.xml maven-compiler-plugin 3.1 1.8 1.8
public interface UserDao {
int insertUser(User user);
List selectUser();
}
创建mybatis主配置文件insert into user values(#{userid},#{username},#{password},#{sex},#{email})
以下文件中连接数据库部分交给spring配置文件
创建Service接口和实现类
public interface UserService {
int adduser(User user);
List queryUser();
}
package com.hdu.service.impl;
import com.hdu.dao.UserDao;
import com.hdu.domain.User;
import com.hdu.service.UserService;
import java.util.List;
public class UserServiceImpl implements UserService {
private UserDao userDao;
//使用set注入来赋值
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public int adduser(User user) {
int nums=userDao.insertUser(user);
return nums;
}
@Override
public List queryUser() {
List users=userDao.selectUser();
return users;
}
}
创建Spring的配置文件
重点部分
创建数据池——duird
连接数据库 代替Mybatis中的功能
声明mybatis中的SQLSessionFactoryBean类,其可以创建SqlSessionFactory
创建dao对象01——读取mybatis的主配置文件——其可以访问sql相关的接口类和实体类
创建dao对象02——通过Service去访问dao
测试类
package com.hdu;
import com.hdu.dao.UserDao;
import com.hdu.domain.User;
import com.hdu.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class MyTest {
@Test
public void Test(){
String config="applicationcontext.xml";
ApplicationContext ctx=new ClassPathXmlApplicationContext(config);
String[] name=ctx.getBeanDefinitionNames();
for (String na:name
) {
System.out.println("容器名称"+na+"*"+ctx.getBean(na));
}
}
@Test
public void Test02(){
String config="applicationcontext.xml";
ApplicationContext ctx=new ClassPathXmlApplicationContext(config);
UserDao dao=(UserDao) ctx.getBean("userDao");
User user=new User();
user.setUserid(160);//主键不能重复
user.setUsername("张三");
user.setPassword("2020");
user.setSex("男");
user.setEmail("187182@");
int nums=dao.insertUser(user);
System.out.println(nums);
List users=dao.selectUser();
for (User u:users
) {
System.out.println(u);
}
}
@Test
public void TestService(){
String config="applicationcontext.xml";
ApplicationContext ctx=new ClassPathXmlApplicationContext(config);
UserService service=(UserService) ctx.getBean("UserService");
User user=new User();
user.setUserid(200);//主键不能重复
user.setUsername("张三");
user.setPassword("2020");
user.setSex("男");
user.setEmail("187182@");
int nums=service.adduser(user);
//spring 和mybatis 事务自动提交 无需执行SqlSess.commit()
System.out.println(nums);
}
@Test
public void TestServiceSelect(){
String config="applicationcontext.xml";
ApplicationContext ctx=new ClassPathXmlApplicationContext(config);
UserService service=(UserService) ctx.getBean("UserService");
List list=service.queryUser();
for (User u:list
) {
System.out.println(u);
}
}
}
Spring开启事务
Spring进行事务管理的常用API
Spring进行事务管理的常用API
1)PlatformTransactionManager:平台事务管理器
Spring进行事务操作时候,主要使用一个PlatformTransactionManager接口,它表示事务管理器,即真正管理事务的对象。
Spring并不直接管理事务,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,也就是将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。
Spring针对不同的持久化框架,提供了不同PlatformTransactionManager接口的实现类:
org.springframework.jdbc.datasource.DataSourceTransactionManager :使用 Spring JDBC或iBatis 进行持久化数据时使用
org.springframework.orm.hibernate3.HibernateTransactionManager :使用 Hibernate版本进行持久化数据时使用
2)Spring的这组接口是如何进行事务管理的
平台事务管理器根据事务定义的信息进行事务的管理,事务管理的过程中产生一些状态,将这些状态记录到TrancactionStatus里面。
3)TrancactionStatus:事务的状态
在上面 PlatformTransactionManager 接口有一个方法getTransaction(),这个方法返回的是 TransactionStatus对象,然后程序根据返回的对象来获取事务状态,然后进行相应的操作。
而 TransactionStatus 这个接口的内容如下:
这个接口描述的是一些处理事务提供简单的控制事务执行和查询事务状态的方法,在回滚或提交的时候需要应用对应的事务状态。



