- 一、AOP思想
- 1、AOP术语
- 2、Pointcut语法
- 二、AOP开发
- 1、导入依赖
- 2、配置AOP(XML方式)
- 3、各种时机的增强细节
- 4、注解配置AOP
Spring系列
- Spring — Spring简介、入门、配置 , IoC和DI思想
- Spring — IoC核心(基于XML)、DI核心(基于XML)
- Spring — 使用IoC和DI模拟注册案例、注解配置IoC和DI
- Spring — 静态代理、动态代理、拦截器思想
- Spring — AOP思想、AOP开发、Pointcut语法、注解配置AOP
- Spring — DAO层、Spring JDBC、Spring事务控制
- Spring — XML配置事务、注解+XML、纯注解的配置方式
- Spring整合MyBatis
- Spring Java Config — 组件注册相关注解
- Spring Java Config — 常用注解
跳转到目录
在开发中,为了给业务方法中增加日志记录,权限检查,事务控制等功能,此时我们需要去修改业务方法代码,考虑到代码的重用性,我们可以考虑使用OOP的继承或组合关系
来消除重复, 但是无论怎么样, 我们都会在业务方法中纵向地增加这些功能方法的调用代码。
此时,既不遵循开闭原则
,也会为后期系统的维护带来很大的麻烦。这些零散存在于业务方法中的功能代码,我们称之为横切面关注点,横切面关注点不属于业务范围,应该从业务代码中剥离出来。为了解决该问题, OOP思想是不行了,得使用AOP思想。
AOP(Aspect Oritention Programming): (在不修改源代码就能做到功能增强
)
把一个个的横切关注点
放到某个模块中去,称之为切面。那么每一个的切面都能影响业务的某一种功能,切面的目的就是功能增强,如日志切面就是一个横切关注点,应用中许多方法需要做日志记录的只需要插入日志的切面即可。
这种面向切面编程的思想就是AOP思想;
跳转到目录
-
Joinpoint : 连接点,被拦截到需要被增强的方法。where :去哪里做增强
-
Pointcut : 切入点,哪些包中的哪些类中的哪些方法,可认为是连接点的集合。where:去哪些地方做增强
-
Advice : 增强(额外功能),当拦截到Joinpoint之后,在方法执行的什么时机( when )做什么样(what)的增强。根据时机分为:前置增强、后置增强、异常增强、最终增强、环绕增强;
-
Aspect : 切面, Pointcut+ Advice ,去
哪些地方+在什么时机+做什么增强
-
Target : 目标对象,被代理的目标对象
-
Weaving : 织入,把Advice加到Target.上之后,创建出Proxy对象的过程。
-
Proxy : 一个类被AOP织入增强后,产生的代理类
-
Advice : (增强)执行时机:
跳转到目录
-
AOP的规范本应该由SUN公司提出,但是被AOP联盟捷足先登。AOP联盟在制定AOP规范时,首先就要解决一个问题: 怎么表示切入点。也就是说怎么表达需要在哪些方法上做增强。这是一个如何表示WHERE的问题。
-
AOP规范后,面向切面编程的框架AspectJ也就应运而生了, 同时也确定如何去表达这个WHERE。
(表示在哪些包下的哪些类中的哪些方法上做切入增强)
:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)throws-pattern?)
execution(? ? ) ?)
? 表示可写可不写
-
*
: 匹配任何部分,但是只能表示一个单词 -
..
: 可用于全限定名中和方法参数中,分别表示 包以及子包 和 0到N个参数。
常见的写法:(对应表达式从后往前看) execution(* cn.sunny.wms.service.*.*(..))
: 表示对service包下的所有类所有方法做增强 execution(* cn.sunny.wms.service.*Serice.*(..))
: 表示对service包下所有以Service为后缀的类的所有方法做增强 execution(* cn.sunny..service.*Service.*(..)
: 表示对sunny包及其子包下的service包中的以Service为后缀的类的所有方法做增强
跳转到目录
1、导入依赖跳转到目录 首先导入AOP织入–>Maven依赖
org.aspectj
aspectjweaver
1.9.4
2、配置AOP(XML方式)
跳转到目录 代码
// domain
public class Employee1 {
}
// ----------------------------------------------
// dao包
public interface EmployeeDao1 {
void save(Employee1 emp);
void update(Employee1 emp);
}
public class EmployeeDaoImpl1 implements EmployeeDao1 {
public void save(Employee1 emp) {
System.out.println("保存员工");
}
public void update(Employee1 emp) {
System.out.println("修改员工信息");;
}
}
// ----------------------------------------------
// -----------------原始功能------------------
// service包
public interface EmployeeService1 {
void save(Employee1 emp);
void update(Employee1 emp);
}
public class EmployeeServiceImpl1 implements EmployeeService1 {
private EmployeeDao1 dao1;
public void setDao1(EmployeeDao1 dao1) {
this.dao1 = dao1;
}
public void save(Employee1 emp) {
dao1.save(emp);
System.out.println("保存成功");
}
public void update(Employee1 emp) {
dao1.update(emp);
throw new RuntimeException("故意出错");
}
}
// ----------------------------------------------
// -----------------额外功能------------------
// 事务管理器(模拟)
public class TransactionManager2 {
public void begin(){
System.out.println("开启事务");
}
public void commit(){
System.out.println("提交事务");
}
public void rollback(){
System.out.println("回滚事务");
}
public void close(){
System.out.println("释放资源");
}
}
xml文件
测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdkDynamicProxyTest {
// com.sun.proxy.$Proxy14
@Autowired
private EmployeeService1 service1;
@Test
public void testSave(){
System.out.println(service1.getClass());
service1.save(new Employee1());
}
@Test
public void testUpdate(){
service1.update(new Employee1());
}
}
跳转到目录
3.1、各种增强增强的时机 根据增强的时机不同,化为多种增强
代码
// TransactionManager类
public class TransactionManager1 {
// 使用JoinPoint类获取被增强方法的信息
// 必须作为增强方法的第一个参数
public void begin(JoinPoint jp){
System.out.println("代理对象:" + jp.getThis().getClass());
System.out.println("目标对象:" + jp.getTarget().getClass());
System.out.println("被增强方法的参数:" + Arrays.toString(jp.getArgs()));
System.out.println("连接点方法签名:" + jp.getSignature());
System.out.println("当前连接点的类型:" + jp.getKind());
System.out.println("开启事务");
}
public void commit(JoinPoint jp){
System.out.println("提交事务");
}
public void rollback(JoinPoint jp, Throwable exception){
System.out.println("回滚事务: " + "异常信息:" + exception);
}
public void close(JoinPoint jp){
System.out.println("释放资源");
}
public Object aroundMethod(ProceedingJoinPoint jpj){
Object ret = null;
System.out.println("开启事务");
try {
//System.out.println(".....执行真实对象中的方法");
ret = jpj.proceed(); // 调用真实对象的方法
System.out.println("提交事务");
} catch (Throwable e){
System.out.println("回滚事务:" + "异常信息:" + e.getMessage());
} finally {
System.out.println("释放资源");
}
return ret;
}
}
xml文件
4、注解配置AOP
跳转到目录
// domain
public class Employee1 {
}
// ----------------------------------------------
// dao包
public interface EmployeeDao1 {
void save(Employee1 emp);
void update(Employee1 emp);
}
@Repository
public class EmployeeDaoImpl1 implements EmployeeDao1 {
public void save(Employee1 emp) {
System.out.println("保存员工");
}
public void update(Employee1 emp) {
System.out.println("修改员工信息");;
}
}
// ----------------------------------------------
// service包
public interface EmployeeService1 {
void save(Employee1 emp);
void update(Employee1 emp);
}
// ------------- 原始功能----------------
@Service
public class EmployeeServiceImpl1 implements EmployeeService1 {
@Autowired
private EmployeeDao1 dao1;
public void save(Employee1 emp) {
dao1.save(emp);
System.out.println("保存成功");
}
public void update(Employee1 emp) {
dao1.update(emp);
throw new RuntimeException("故意出错");
}
}
// ----------------------------------------------
// 事务管理器(模拟)
@Component // IoC注解
@Aspect // 配置一个切面 // ------------- 组装切面(切入点+额外功能)----------------
public class TransactionManager1 { // ------------- 额外功能----------------
// ------------- 切入点 (哪些地方需要添加额外功能)----------------
// 配置在哪些包中的哪些类中的哪些方法上做增强
//XML:
@Pointcut("execution(* com.sunny._02_dynamic_proxy.service.*Service1.*(..))")
public void txPoint(){
}
@Before("txPoint()")
public void begin(JoinPoint jp){
System.out.println("开启事务");
}
@AfterReturning("txPoint()") // 操作完成之后
public void commit(){
System.out.println("提交事务");
}
@AfterThrowing(value = "txPoint()", throwing = "exception")
public void rollback(Throwable exception){
System.out.println("回滚事务: " + "异常信息:" + exception);
}
@After("txPoint()")
public void close(){
System.out.println("释放资源");
}
//@Around("txPoint()") // 可以替代上面的几个注解
public Object aroundMethod(ProceedingJoinPoint jpj){
Object ret = null;
System.out.println("开启事务");
try {
//System.out.println(".....执行真实对象中的方法");
ret = jpj.proceed(); // 调用真实对象的方法
System.out.println("提交事务");
} catch (Throwable e){
System.out.println("回滚事务:" + "异常信息:" + e.getMessage());
} finally {
System.out.println("释放资源");
}
return ret;
}
}
xml文件