文章目录
一、知识点回顾
(1)动态代理proxy
- (1)动态代理,必须要有一个接口
- (2)动态代理的三个参数
代理类,与被代理类 地位是一样的
所以,有相同的接口(ClassLoader),相同的类加载器 - (3)invoke方法
参1 一般不用,代理对象
参2 表示要增强哪个方法
Object returnValue = method.invoke(laoZong,args);
(2)AOP的术语
- (1) 目标类target:就是我们需要增强的那个类 LaoZong.class
- (2) 代理类proxy:就是自定义的代理的对象
- (3) 连接点joinPoint:程序执行的某个特定位置,Spring仅支持方法的连接点
- (4) 切入点pointCut:就是在目标类中实际增强的方法
- (5) 织入weave:就是将代理类中需要增强的方法放入到目标类中去执行的过程
- (6) 引介Introduction:引介是一种特殊的增强,它为类添加一些属性和方法(课程不使用)
- (7) 通知advice:将代理对象中的方法应用到目标类的过程中产生的结果。
- (8)
切面aspect
:所有的切入点和代理对象的方法组成在一起 构成了切面
二、 SpringAOP开发
(1)AOP切面编程-基于XML—环境搭建
- (1)环境搭建 pom.xml
aspectj - (2)编写代码
UserTest 测试类
IUser 接口
UserImpl 方法实现
Advice - (3)AOP配置
只需要思考两个问题
》哪些方法要增强
》在方法的哪个位置调用其他方法
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
</dependencies>
IUser.java(共同接口)
public interface User {
public void work();
}
UserImpl.java
public class UserImpl implements User {
@Override
public void work() {
System.out.println("我爱加班");
}
}
Advice .java
public class Advice {
public void writeLog(){
System.out.println("写一篇日志");
}
}
<!--在此进行AOP基于配置-->
<!--1:创建被增强类对象:UserImpl-->
<bean id="userImpl" class="com.smp.xml_aop.UserImpl"></bean>
<!--2:创建增强对象:Advice-->
<bean id="advice" class="com.smp.xml_aop.Advice"></bean>
<!--3:开始基于AOP增强
3.1 我要对UserImpl类的work方法进行前置增强,
在work方法之前先执行Advice类中writeLog方法
-->
<aop:config>
<!--1:配置切入点(配置要增强的方法)
id:表示给要增强的方法切入点进行一个编号
-->
<aop:pointcut id="point01" expression="execution(public void com.smp.xml_aop.UserImpl.work())"/>
<!--2:配置切面:增强的方式
ref:用来指定增强类
-->
<aop:aspect ref="advice">
<!--配置增强的细节:要用那个方法去给work增强,是放在work的前面和后边-->
<aop:before method="writeLog" pointcut-ref="point01"/>
</aop:aspect>
</aop:config>
applicationContext.xml
<?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: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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 创建UserImpl对象 目标类 -->
<bean id="userImpl" class="com.smp.service.Impl.UserImpl"/>
<!-- 创建Advice对象-->
<bean id="advice" class="com.smp.service.Advice"/>
<!-- 配置他们的增强关系 生成一个代理类-->
<aop:config >
<aop:pointcut id="work" expression="execution(public void com.smp.service.Impl.UserImpl.work())"/>
<!-- 我想在work方法执行 之后调用一下writeLog-->
<aop:aspect ref="advice">
<aop:after method="writeLog" pointcut-ref="work"/>
</aop:aspect>
</aop:config>
</beans>
(2)AOP切面编程-切面表达式
- (1)什么是切面表达式
execution([修饰符] 返回值类型 包.类.方法(参数列表) );
- (2)切面表达式有什么用?
符合表达式的方法,会被增强
使用*表示任意的内容
使用…表示包与子包下面的子类
使用…表示(…)任意参数
1:完全写法
execution(public void com.smp.xml_aop.UserImpl.work(int) );
2:-修饰符省略
execution( void com.smp.xml_aop.UserImpl.work(int) );
3:简化2-返回值类型写通配符
execution(* com.smp.xml_aop.UserImpl.work(int) );
4:简化3-包名写通配符
execution(* *.*.*.UserImpl.work(int) );
5:简化4-包名通配符简化
execution(* *..UserImpl.work(int) );
6:简化5-类名通配符
execution(* *..*.work(int) );
7:简化6-参数写通配符
execution(* *..*.work(..) );
-->
<aop:pointcut id="point01" expression="execution(* *..*.work(..))"/>
-->
<aop:pointcut id="point01" expression="execution(* *..*.addUser(..))"/>
<aop:pointcut id="point02" expression="execution(* *..*.deleteUser(..))"/>
<aop:pointcut id="point03" expression="execution(* *..*.updateUser(..))"/>
<aop:pointcut id="point04" expression="execution(* *..*.queryUser(..))"/>
<aop:pointcut id="point05" expression="execution(* *..*.batchDeleteUser(..))"/>
(3)AOP切面编程-增强方式
增强方式有哪些:
<aop:aspect ref="advice">
<!--配置增强的细节:要用那个方法去给work增强,是放在work的前面和后边-->
<!--1、前置增强-->
<aop:before method="before" pointcut-ref="point01"/>
<!--2、后置增强-->
<aop:after-returning method="afterReturning" pointcut-ref="point02"/>
<!--3、异常增强-->
<aop:after-throwing method="throwable" pointcut-ref="point03"/>
<!--4、环绕增强-->
<aop:around method="around" pointcut-ref="point04"/>
<!--5、最终增强-->
<aop:after method="after" pointcut-ref="point05"/>
</aop:aspect>
实际上是增强四个可选调用位置:
try{
//Before
result =method .invoke(target,args);
//AfterReturning
}catch (InvocationTargetException e){
Throwable targetargetException =e.getTargetException();
//@AfterThrowing
throw targetargetException;
}finally {
{//After
}
简化:joinPoint.proceed(); //切到原来的目标方法,进行执行
Advice
public class Advice {
public void writeLog(){
System.out.println("写一个开发备忘录");
}
public void before(){
System.out.println("before-------");
}
public void after(){
System.out.println("after-------");
}
public void afterReturn(){
System.out.println("afterReturn-------");
}
public void afterThrow(){
System.out.println("afterThrow-------");
}
}
applicationContext.xml
<!-- 配置他们的增强关系 生成一个代理类-->
<aop:config >
<aop:pointcut id="all" expression="execution( * com.wzx.service..*.*(..))"/>
<!-- 我想在work方法执行 之后调用一下writeLog-->
<aop:aspect ref="advice">
<!-- try-->
<aop:before method="before" pointcut-ref="all"/>
<!-- 有可能程序正常运行-->
<aop:after-returning method="afterReturn" pointcut-ref="all"/>
<!-- catch-->
<aop:after-throwing method="afterThrow" pointcut-ref="all"/>
<!-- finally-->
<aop:after method="after" pointcut-ref="all"/>
</aop:aspect>
</aop:config>
环绕增强:
Advice
public void arround(ProceedingJoinPoint point ){//参目标类中的任意方法
try{
//执行before
before();
System.out.println("arround-------");
point.proceed();//对应你调用的UserImpl中的任意方法
//执行正常返回
afterReturn();
}catch (Throwable e){
//补救方法
afterThrow();
}finally {
//释放资源的方法
after();
}
}
applicationContext.xml
<!-- 配置他们的增强关系 生成一个代理类-->
<aop:config >
<aop:pointcut id="all" expression="execution( * com.wzx.service..*.*(..))"/>
<!-- 我想在work方法执行 之后调用一下writeLog-->
<aop:aspect ref="advice">
<aop:around method="arround" pointcut-ref="all"/>
</aop:aspect>
</aop:config>
(4)AOP切面编程-注解
- (1)spring注解配置
一个xml开启注解自动代理
几个注解
切面@Aspect
四个位置注解
Advice
@Component
@Aspect
public class Advice {
public void writeLog(){
System.out.println("写一个开发备忘录");
}
//try{ }
// @Before("execution( * com.wzx.service..*.*(..))")
public void before(){
System.out.println("before-------");
}
//@AfterReturning("execution( * com.wzx.service..*.*(..))")
public void afterReturn(){
System.out.println("afterReturn-------");
}
//catch(exception e){ }
// @AfterThrowing("execution( * com.wzx.service..*.*(..))")
public void afterThrow(){
System.out.println("afterThrow-------");
}
//finally
// @After("execution( * com.wzx.service..*.*(..))")
public void after(){
System.out.println("after-------");
}
@Around("execution( * com.wzx.service..*.*(..))")
public void arround(ProceedingJoinPoint point ){//参目标类中的任意方法
try{
//执行before
before();
System.out.println("arround-------");
point.proceed();
//执行正常返回
afterReturn();
}catch (Throwable e){
//补救方法
afterThrow();
}finally {
//释放资源的方法
after();
}
}
}
applicationContext.xml
<?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">
<!--包扫描创建对象 扫描包与它下面的子包中的所有类-->
<context:component-scan base-package="com.wzx.service"/>
<!--开启自动AOP代理-->
<aop:aspectj-autoproxy/>
</beans>