1. 代理
1.1 静态代理
- 静态代理,一个角色就要一个代理
1.2 动态代理
- JDK 动态代理基于接口,被代理对象必须实现接口
- CGLIB基于类,Java 字节码
1.3 正交
- 线性无关
- 运行时创建一个代理类
2. AOP
- Aspect Oriented Programing,即面向切面编程
- AOP 采取横向抽取机制
- 应用场景
- 性能监测
- 访问控制
- 事物管理
- 日志记录
2.1 Joinpoint(连接点)
- Spring 只支持方法类型的连接点
2.2 Pointcut(切入点)
- 切入点,定义要拦截哪些类的哪些方法
2.3 Advice(通知/增强)
- Advice 增强,定义了拦截之后方法要做什么
- 拦截到 JoinPoint 之后要做的事情
2.4 Advisor(通知器)
- 连接 Advice 和 Pointcut
2.5 切面(Aspect)
- 切面,切入点和通知的抽象,定义切入点和通知
- 通知:定义了拦截之后方法要做什么
- 切点
<aop:pointcut id="logPoint" expression="execution(* com.example.concrete.service..*.*(..))"/>
- spring-framework/docs/2.0.x/reference/aop.html
@Component
@Aspect
public class LogCut {
// 切入点
@Pointcut(value = "execution(* com.example.concrete.interceptor.*.*(..))")
public void cut() {}
@Before(value = "cut()")
public void before() {
}
}
@Component 将对象交给 IOC 容器进行实例化
@Aspect 声明当前类是一个切面
2.6 Introduction(引介)
2.7 Target(目标对象)
2.8 Weaving(织入)
- 动态织入,Spring AOP 采用基于运行时增强的代理技术
- 静态织入,AspectJ 采用编译期织入
2.9 Proxy(代理)
3. Spring AOP
3.1 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
https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
https://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 开启自动扫描 -->
<context:component-scan base-package="com.spring"/>
<!-- 配置 AOP 代理 -->
<aop:aspectj-autoproxy/>
</beans>
<aop:config>
<aop:aspect id="" ref="aspectClassBeanName">
<aop:pointcut id="pointcutMethodName" expression="execution...." />
<aop:before method="beforMethodName" pointcut-ref="pointcutMethodName" />
<aop:aspect>
</aop:config>
3.2 注解方式
- @Aspect 声明切面
- @Pointcut: @Before, @Around, @After, @AfterReturning, @AfterThrowing
- @Pointcut("匹配规则")
.*.* 所有包的所有方法, (..) 方法参数
-
@annotation
匹配被指定注解标记的所有方法
java.lang.reflect.InvocationHandler
@Pointcut("execution(public String com.baeldung.pointcutadvice.dao.FooDao.findById(Long))")
@Pointcut("execution(* com.baeldung.pointcutadvice.dao.FooDao.*(..))")
// the execution of any method defined by the AccountService interface:
execution(* com.xyz.service.AccountService.*(..))
// service package
execution(* com.xyz.service.*.*(..))
// service package or a sub-package
execution(* com.xyz.service..*.*(..))
@Service
public class GreetServiceImpl implements GreetService {
@Override
@LogAnno
public String greeting() {
System.out.println("run method");
return "hello";
}
}
@Aspect
@Component
public class AnnotationIntercept {
@Pointcut("@annotation(com.example.concrete.aop.LogAnno)")
public void pointCut() {}
@Before("pointCut()")
public void before() {
System.out.println("before...");
}
@Around("pointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
System.out.println("around start");
Object obj = point.proceed();
System.out.println("around end");
return obj;
}
@AfterReturning(value = "execution(* com.example.concrete.interceptor.*.*(..))", returning = "result")
public void AfterReturning(JoinPoint joinPoint, Object result) {
Object[] args = joinPoint.getArgs();
System.out.println("after returning: " + JSON.toJSONString(args));
System.out.println("after result: " + JSON.toJSONString(result));
}
}
// -------
around start
before...
run method
after returning...
after...
around end
网友评论