作用:将通知/增强
作用于具体切入点
基本格式:
指示符(表达式)
1.指示符分类:
【execution】:用于匹配方法执行的连接点;
within:用于匹配指定类型内的方法执行;
this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;
@within:用于匹配所以持有指定注解类型内的方法;
@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
@args:用于匹配当前执行的方法传入的参数持有指定注解的执行;
@annotation:用于匹配当前执行方法持有指定注解的方法;
2.表示式格式:
execution([修饰符] 返回值类型 包名.类名.方法名(参数类型列表) [throws 异常])
返回值:
* 表示返回任意值
包名:
com.czxy.user.dao 具体包名
com.czxy.*.dao 任意模块的dao
com.czxy.*sys.dao 固定后缀的包
com.czxy.user.dao.. 任意子包 (dao.impl包)
类名
UserDao 具体类名
*Dao 固定后缀
User* 固定前缀
* 任意
方法:
findAll 具体方法名
find* 固定前缀
*All 固定后缀
* 任意
(参数类型列表):
() 无参
(int) 第一个整形参数
(int,int) 两个参数都是整形
(*) 任意一个参数
(..) 参数任意
// 完整的实例代码
* * com.czxy.service..User*.select*(..)
// 常见的写法
* com.czxy.service..*.*(..)
spring通知共5个分类:前置通知、后置通知、环绕通知、抛出异常通知、最终通知
try{
// 前置通知、环绕通知
// 目标类的方法
// 后置通知、环绕通知
} catch() {
// 抛出异常通知
} finally {
// 最终通知
}
//前置通知 @Before
//后置通知 @AfterReturning
//环绕通知 @Around
//抛出异常通知 @AfterThrowing
//最终通知 @After
@Before("execution(* com.czxy.demo16_aop.dao..*.*(..))")
public void myBeforeAdvice() {
System.out.println("开启事务");
}
// 返回值:类型 变量名
// 类型,必须是Object
// 变量名,需要通过returning设置,且提供对应的方法参数
@AfterReturning(value="切入点表达式", returning = "返回值变量名")
public void 方法名(Object 返回值变量名) {
}
@AfterReturning(value="execution(* com.czxy.demo16_aop.dao..*.*(..))", returning = "obj")
public void myAfterReturningAdvice(JoinPoint joinPoint, Object obj) {
System.out.println("目标类:" + joinPoint.getTarget());
System.out.println("方法名:" + joinPoint.getSignature().getName());
System.out.println("返回值:" + obj);
System.out.println("提交事务");
}
// 环绕通知:必须手动执行目标方法(连接点) ProceedingJoinPoint 可执行连接点
@Around("myPointcut()")
public Object myAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前2");
// 执行目标
Object proceed = proceedingJoinPoint.proceed();
System.out.println("环绕后2");
return proceed;
}
// 异常通知,可以获得异常具体信息,异常类型(Throwable) 异常变量名
@AfterThrowing(value="execution(* com.czxy.demo16_aop.dao..*.*(..))",throwing = "e")
public void myAfterThrowingAdvice(Throwable e) {
System.out.println("异常通知:" + e.getMessage());
}
@After("execution(* com.czxy.demo16_aop.dao..*.*(..))")
public void myAfterAdvice() {
System.out.println("释放资源");
}
使用 @Pointcut 抽取切入点,通过 方法名 进行引用。
package com.czxy.demo16_aop.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* @author 桐叔
* @email [email protected]
*/
@Component
@Aspect
public class MyAspect2 {
// 抽取公共切入点表达式
@Pointcut("execution(* com.czxy.demo16_aop.dao..*.*(..))")
private void myPointcut() {
}
// 前置通知
// @Before("myPointcut()")
public void myBeforeAdvice() {
System.out.println("开启事务2");
}
// 后置通知
// @AfterReturning(value="myPointcut()", returning = "obj")
public void myAfterReturningAdvice(JoinPoint joinPoint, Object obj) {
System.out.println("目标类2:" + joinPoint.getTarget());
System.out.println("方法名2:" + joinPoint.getSignature().getName());
System.out.println("返回值2:" + obj);
System.out.println("提交事务2");
}
// 环绕通知:必须手动执行目标方法(连接点) ProceedingJoinPoint 可执行连接点
@Around("myPointcut()")
public Object myAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前2");
// 执行目标
Object proceed = proceedingJoinPoint.proceed();
System.out.println("环绕后2");
return proceed;
}
// 异常通知,可以获得异常具体信息,异常类型(Throwable) 异常变量名
@AfterThrowing(value="myPointcut()",throwing = "e")
public void myAfterThrowingAdvice(Throwable e) {
System.out.println("异常通知2:" + e.getMessage());
}
@After("myPointcut()")
public void myAfterAdvice() {
System.out.println("释放资源2");
}
}
package com.czxy.sm.mapper;
import com.czxy.sm.domain.User;
import tk.mybatis.mapper.common.Mapper;
/**
* @author 桐叔
* @email [email protected]
*/
public interface UserMapper extends Mapper<User> {
}
package com.czxy.sm.service;
import com.czxy.sm.domain.User;
import java.util.List;
/**
* @author 桐叔
* @email [email protected]
*/
public interface UserService {
/**
* 查询所有
* @return
*/
public List<User> selectAll();
}
package com.czxy.sm.service.impl;
import com.czxy.sm.domain.User;
import com.czxy.sm.mapper.UserMapper;
import com.czxy.sm.service.UserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* @author 桐叔
* @email [email protected]
*/
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Override
public List<User> selectAll() {
return userMapper.selectAll();
}
}
package com.czxy.sm.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
/**
* @author 桐叔
* @email [email protected]
*/
@Configuration
@PropertySource("classpath:db.properties")
@ComponentScan(basePackages = "com.czxy.sm")
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
public DataSource dataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driver);
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
return druidDataSource;
}
}
db.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_db1
jdbc.username=root
jdbc.password=1234
package com.czxy.sm.config;
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import tk.mybatis.spring.mapper.MapperScannerConfigurer;
import javax.sql.DataSource;
import java.util.Properties;
/**
* @author 桐叔
* @email [email protected]
*/
public class MyBatisConfiguration {
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
//1 创建工厂
// 1.通过工厂bean创建对象,最后需要调用 getObject()获得具体的对象
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
//2 设置数据-- SqlMapConfig.xml 配置信息
// 1.1 设置数据源
factoryBean.setDataSource(dataSource);
// 1.2 设置别名包扫描
factoryBean.setTypeAliasesPackage("com.czxy.sm.domain");
// 1.3 全局配置:驼峰映射
org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
config.setMapUnderscoreToCamelCase(true);
factoryBean.setConfiguration(config);
// 2 插件配置
// 2.1 分页插件
PageHelper pageHelper = new PageHelper();
Properties pageProps = new Properties();
pageProps.setProperty("dialect", "mysql");
pageProps.setProperty("rowBoundsWithCount", "true");
pageHelper.setProperties(pageProps);
factoryBean.setPlugins(new Interceptor[] { pageHelper });
// 返回SqlSessionFactory
return factoryBean.getObject();
}
/**
* 扫描Dao的包,查找各种XxxMapper接口,创建好UserMapper等对象存入到IOC的容器中
* @return
*/
@Bean
public MapperScannerConfigurer mapperScanner() {
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setBasePackage("com.czxy.sm.mapper");
return configurer;
}
}
package com.czxy.sm;
import com.czxy.sm.config.MyBatisConfiguration;
import com.czxy.sm.config.SpringConfiguration;
import com.czxy.sm.domain.User;
import com.czxy.sm.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
/**
* @author 桐叔
* @email [email protected]
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class, MyBatisConfiguration.class})
public class TestSM {
@Resource
private UserService userService;
@Test
public void testDemo() {
List<User> list = userService.selectAll();
list.forEach(System.out::println);
}
}
总结:
1,AOP 五种通知类型各自对应各自的使用场景,虽然有点小乱但大体规则,可以根据增强的需要使用。
2,Mybatis和Spring整合,主要就是两个配置类的串联,Spring配置类将数据源配置并带入Mybatis配置类中,Mybatis配置类再配置以前SqlMapConfig中的配置即可,剩下的简单调用就行。
不错,离工作又进一天