AOP概述
AOP是什么
- AOP是一种编程范式
- 解决特定问题
- 是OOP的补充
AOP的优势
- 解决重复性代码
- 关注点分离(集中处理某一关注点/横切逻辑)
- 水平分离:展示层、服务层、持久层
- 垂直分离:模块划分(订单、库存等)
- 切面分离:分离功能性需求与非功能性需求
- 可以很方便添加/删除关注点
- 代码入侵少,增强代码可读性和可维护性
应用场景
- 权限控制
- 缓存控制
- 事务控制
- 审计日志
- 性能监控
- 分布式追踪
- 异常处理
AOP的使用
使用方式
- 基于XML
- 基于注解
三大注解
- @Aspect:标识类为切面类
- @Pointcut:描述在哪些类哪些方法执行切面方法
- Advice:执行方法的时机
切面表达式(Pointcut Expression)
- 指示器(designators)
- within表达式(包匹配)
- 对象匹配
- 参数匹配
- 注解匹配
- execution表达式
- modifier-pattern 修饰符
- ret-type-pattern!! 返回值
- declaring- type-pattern 包名
- name-pattern(param-pattern)!! 方法名(参数名)
- throws-pattern (抛出异常)
- 注:1. 有!!的不可省略 2.支持通配符
- advice注解
- 通配符(wildcards)
- * :匹配任意数量的字符
- + :匹配指定类及其子类
- … :一般用于匹配任意数的子包或参数
- 运算符(operators)
- && :与
- || :或
- ! :非
AOP实现原理
-
织入(Weaving),AOP术语。把切面(aspect)连接到其它的应用程序类型或者对象上,并创建一个被通知(advised)的对象,这样的行为叫做织入。
-
织入时机
-
运行时织入使用代理对象实现
代理模式
代理对象将目标方法交给目标对象执行,本身执行额外的逻辑方法。
静态代理
- 建一个接口,接口中定义相应(代理对象和目标对象都要实现)的 方法
public interface Subject{
void test();
}
- 目标类(实现上述接口)
public class RealSubject() implements Subject{
@Override
public void tset(){
System.out.printin("Object Class");
}
}
- 代理类(实现上述接口)
public class Proxy() implements Subject{
private RealSubject realSubject;
public Proxy(RealSubject realSubject){
this.realSubject = realSubject;
}
@Override
public void test(){
System.out.printin("Before");
try{
realSubject.test();
}catch(Exception e){
System.out.println("ex:"+e.getmessage());
throw e;
}finally{
System.out.println("After");
}
}
}
- 客户端调用类
public class Client{
public static void main(String[] args){
//通过接口
Subject subject = new Proxy(new RealSubject());
subject.test();
}
}
动态代理
(静态代理缺点:不灵活,重复代码多)
- 基于接口代理(jdk)
- 类:java.lang.reflect.Proxy(通过该类动态生成代理类)
- 代理类实现接口:InvocationHandler
- jdk代理只能基于接口动态代理
- 动态代理类
- 实现接口的方法
- 引用目标方法
- 构造器注入目标方法
- 通过反射调用目标方法
public class JdkProxySubject implements InvocationHandler{
//引用目标方法
private RealSubject realSubject;
//用构造器注入目标方法
public JdkProxySubject(RealSubject realSubject){
this.realSubJect=realSubject;
}
//实现接口的方法
@Override
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
System.out.println("before");
Object result = null;
try{
//调用目标方法
//利用反射构造目标对象
result=method.invoke(realSubject,args);
}catch(Exception e){
System.out.println("ex:"+e.getMessage());
throw e;
}finally{
System.out.println("after");
}
return result;
}
}
- 客户端调用(使用Proxy)
public class Client{
public static void main(String[] args){
//使用Proxy构造对象
//参数
//java泛型需要转换一下
Subject subject = (Subject) java.lang.reflect.Proxy.newProxyInstance(Client.class.getClassLoader(),new Class[]{Subject.class},new JdkProxySubject(new RralSubject()));
//调用方法
subject.test;
}
}
- 原理解析
- 调用Proxy.newProxyInstance生成代理类的实现类:
- 调用getProxyClass0//寻找或生成指定代理类
(从缓存中取,如果没有,就生成一个放在缓存中。通过ProxyClassFactory生成)
- 缓存调用ProxyClassFactory生成代理类
- ProxyGenerator使用生成的代理类的名称,接口,访问标志生成proxyClassFile字节码
- newInstance(生成字节码之后利用反射生成实例)
- 基于继承代理(cglib)
- 代理类
public class CglibMethodInterceptor implements MethodInterceptor{
@Override
public Object intercept(Object obj,Method method,Object
[] args,MethodProxy proxy )throws Throwable{
System.out.println("before cgpib");
Object result = null;
try{
//利用反射创建代理对象
result = proxy.invokeSuper(obj,args);
}catch(Exception e){
System.out.println("ex:"+e.getMessage());
throw e;
}finally{
System.out.println("after cglib");
}
return result;
}
}
- 调用类
public class Client{
public static void main(String[] args){
//生成
Enhancer enhancer=new Enhancer;
//目标类
enhancer.setSuperclass(RealSubject.class);
//代理类
enhancer.setCallback(new CglibMethodInterceptor());
//生成代理类对象
Subject subject=enhancer.create();
subject.hello;
}
}
- 两种动态代理的对比和选择
AOP链式调用
- 责任链模式
- Chain类:
import java.util.List;
public class Chain{
private List<ChainHandler> handlers;
private int index = 0;
//构造器
public Chain(List<ChainHandler> handlers){
this.handlers = handlers;
}
public void procceed(){
if(index >= handlers.size()){
return ;
}
if(index >= handlers.size()){
return ;
}
handlers.get(index++).execute(this);
}
}
- ChainHandler类:
public abstract class ChainHandler{
public void execute(Chain chain){
handlerProcess();
chain.procceed();
}
//抽象方法
protected abstract void handlerProcess();
}
- ChainClient类:
import java.util.Arrays;
import java.util.List;
public class ChainClient{
static class ChainHandlerA extends ChainHandler{
@Override
protected void handlerProcess(){
System.out.println("Chain A");
}
}
static class ChainHandlerB extends ChainHandler{
@Override
protected void handlerProcess(){
System.out.println("Chain B");
}
}
static class ChainHandlerC extends ChainHandler{
@Override
protected void handlerProcess(){
System.out.println("Chain C");
}
}
public static void main(String[] args){
//声明链式关系
List<ChainHandler> handler = Arrays.asList(new ChainHandlerA(),new ChainHandlerB(),new ChainHandlerC());
Chain chain = new Chain(handler);
chain.procceed();
}
}
AOP注意事项
喜欢的话可以点点关注,或者添加作者微信,欢迎随时来撩