一,什么是SpringAop?
所谓的springaop就是面向切面编程,就是在你的原有项目功能上,通过aop去添加新的功能,这些功能是建立在原有的功能基础上的,而且不会修改原来的动能代码以及功能逻辑。例如你用银行卡购物,购物付款,这是一个功能。付款后,银行向你的手机发送一条取钱信息,这就是新加的功能。也就是实现了增强
二,Springaop的实现机制是什么?
横向抽取机制,那么什么是横向抽取机制呢?所谓的横向抽取机制就是使用动态的代理的方式(cglib代理和jdk代理)来实现对象的代理,实际上我们操作的是假对象。既然有横向抽取机制,那么有没有纵向代理模式呢 ?答案是有的。那么什么是纵向抽取呢?纵向抽取就是把公共的方法写在父类里,所有的类都继承父类,这样就是能调用父类的方法。例如,你购物付款是一个子类的功能,你可能还会取款,这也是一个功能,而在他们结束之后,银行都会发送一个信息给你,这又是一个功能,这个银行给你发送信息是个公共的方法,所以这个发信息的功能就是属于父类的。子类继承父类并调用父类的方法就是纵向抽取。
三,Springaop的使用场景
一般来说:打印日志,还有短信通知啊,权限验证等,都可以使用aop来实现。
四,sringaop的两种实现方式
(1)xml文件配置方式
(2)注解的方式实现
方式一:xml文件方式配置
导入AOPjar包
创建如图所示项目结构
创建核心类的接口
package com.su.service;
public interface BookService {
// 添加
int save(int n);
// 删除
int del();
// 修改
int update();
// 查询
void find();
}
创建核心类(被加强类)
package com.su.service.impl;
import com.su.service.BookService;
public class BookServiceImpl implements BookService {
@Override
public int save(int n) {
System.out.println("添加");
return 1;
}
@Override
public int del() {
System.out.println("删除");
return 1;
}
@Override
public int update() {
System.out.println("修改");
return 1;
}
@Override
public void find() {
System.out.println("查询");
}
}
创建增强类
package com.su.advice;
import org.aspectj.lang.ProceedingJoinPoint;
public class Loger {
public void check(){
System.out.println("前置通知/增强:执行系统的权限验证");
}
public void logPrint(){
System.out.println("后置通知/增强:执行日志的打印");
}
public void exception(){
System.out.println("异常通知/增强:做出异常处理");
}
public void distory(){
System.out.println("最终通知/增强:资源释放");
}
public Object around(ProceedingJoinPoint pjp) {
try {
//前置增强
System.out.println("环绕通知---前置增强");
//通过ProceedingJoinPoint 完成代理对象的方法调用
Object result = null;//定义返回值变量
Object[] args = pjp.getArgs();//获取参数列表
result = pjp.proceed(args);
//后置增强
System.out.println("环绕通知---后置增强");
return result;
} catch (Throwable e) {
//异常通知
System.out.println("环绕通知----异常增强");
throw new RuntimeException(e);
} finally {
//最终增强
System.out.println("环绕通知----最终增强");
}
}
}
配置切点和切面
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1.把所有类的对象交给IOC容器进行管理-->
<bean id="loger" class="com.su.advice.Loger"/>
<bean id="bookService" class="com.su.service.impl.BookServiceImpl"/>
<!--2.AOP的配置:让增强类 的 哪个方法 动态进行何种增强 核心类 的 哪个方法-->
<aop:config>
<!--配置 增强类的哪个方法 对 核心类的哪个方法 进行 何种增强-->
<aop:aspect id="log" ref="loger">
<!-- <aop:before method="check" pointcut="execution(* *..BookServiceImpl.*(..))"/>-->
<!-- <aop:after-returning method="logPrint" pointcut="execution(* *..BookServiceImpl.*(..))"/>-->
<!-- <aop:after-throwing method="exception" pointcut="execution(* *..BookServiceImpl.*(..))"/>-->
<!-- <aop:after method="distory" pointcut="execution(* *..BookServiceImpl.*(..))"/>-->
<!--环绕增强-->
<aop:around method="around" pointcut="execution(* *..BookServiceImpl.*(..))"/>
</aop:aspect>
</aop:config>
</beans>
创建测试类
package com.su.servlet;
import com.su.service.BookService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test01 {
@Test
public void test01(){
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
BookService bookService=context.getBean(BookService.class);
bookService.save(5);
}
}
运行结果
由上面的配置文件可以看出,配置相当复杂,接下来使用spring注解的方式。
方式二:通过springAop注解实现
导入AOPjar包
创建如图所示项目结构
创建核心类的接口
package com.su.service;
public interface BookService {
// 添加
int save(int n);
// 删除
int del();
// 修改
int update();
// 查询
void find();
}
创建核心类(被加强类)
package com.su.service.impl;
import com.su.service.BookService;
public class BookServiceImpl implements BookService {
@Override
public int save(int n) {
System.out.println("添加");
return 1;
}
@Override
public int del() {
System.out.println("删除");
return 1;
}
@Override
public int update() {
System.out.println("修改");
return 1;
}
@Override
public void find() {
System.out.println("查询");
}
}
2创建增强类并打上注解
@Aspec:增强
@Component:定义Spring管理Bean(也就是将标注@Component注解的类交由spring管理)
@Before:前置通知
@AfterReturning:后置通知
@AfterThrowing:异常通知@After:最终通知
@Around:环绕通知
package com.su.advice;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 注解
*/
@Component
//告诉系统loger是增强类
@Aspect
public class Loger {
//@Before:前置通知
@Before("execution(* *..BookServiceImpl.*(..))")
public void check(){
System.out.println("前置通知/增强:执行系统的权限验证");
}
//@AfterReturning:后置通知
@AfterReturning("execution(* *..BookServiceImpl.*(..))")
public void logPrint(){ System.out.println("后置通知/增强:执行日志的打印"); }
//@AfterThrowing:异常通知
@AfterThrowing("execution(* *..BookServiceImpl.*(..))")
public void exception(){ System.out.println("异常通知/增强:做出异常处理"); }
//@After:最终通知
@After("execution(* *..BookServiceImpl.*(..))")
public void distory(){ System.out.println("最终通知/增强:资源释放"); }
//@Around:环绕通知
@Around("execution(* *..BookServiceImpl.*(..))")
public Object around(ProceedingJoinPoint pjp) {
try {
//前置增强
System.out.println("环绕通知---前置增强");
//通过ProceedingJoinPoint 完成代理对象的方法调用
Object result = null;//定义返回值变量
Object[] args = pjp.getArgs();//获取参数列表
result = pjp.proceed(args);
//后置增强
System.out.println("环绕通知---后置增强");
return result;
} catch (Throwable e) {
//异常通知
System.out.println("环绕通知----异常增强");
throw new RuntimeException(e);
} finally {
//最终增强
System.out.println("环绕通知----最终增强");
}
}
}
配置切点和切面
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1.扫描component及同名注解-->
<context:component-scan base-package="com.su"/>
<!--2.开启AOP注解支持-->
<aop:aspectj-autoproxy/>
</beans>
创建测试类
package com.su.servlet;
import com.su.service.BookService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test01 {
@Test
public void test01(){
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
BookService bookService=context.getBean(BookService.class);
bookService.save(5);
}
}
运行结果