Spring AOP自定义实现

上一遍文章研究了Spring AOP实现源码,现在自己也想自己实现。

假如要对以下接口BarService织入Before增强和After增强

接口定义

public interface BarService {
    void doSomething();
}

接口实现

@Service
public class BarServiceImp implements BarService {
    @Override
    public void doSomething() {
        System.out.println("执行原有业务逻辑...");
    }
}

定义注解MyAspect

这个注解必须用@Component定义,因为它也是个Bean,需要Spirng管理

@Component
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAspect {

    String pointCut() default "";

}

MyAspect使用

MyAspect指定拦截FooServiceImp的add方法

@MyAspect(pointCut = "com.ydoing.spring.core.aop.customized.FooServiceImp.add")
public class MyLogAspect {
    public void before(Object[] args) {
        System.out.println("before增强,args[0]:" + args[0] + ", args[1]:" + args[1]);

    }

    public void after(Object[] args) {
        System.out.println("after增强,args[0]:" + args[0] + ", args[1]:" + args[1]);

    }

}

定义增强Advisor

public interface Advisor extends MethodInterceptor, Orderable{

    boolean isMatch(Class<?> clazz, Method method);
}

Advisor本质上是个拦截器

public interface MethodInterceptor {

    Object invoke(MethodInvocation methodInvocation) throws Throwable;

}

Orderable接口是用来排序

public interface Orderable {

    int getOrder();
}

一般接口都用骨架类实现,建议Abstract前缀命名,这里我们Advisor的默认实现为AbstractAdvisor

public abstract class AbstractAdvisor implements Advisor {

    protected int order = 0;

    protected Pattern pattern;

    protected Object aopObj;

    protected Method aopMethod;

    public AbstractAdvisor(Object aopObj, Method aopMethod) {
        this.aopObj = aopObj;
        this.aopMethod = aopMethod;

        String reg = aopObj.getClass().getAnnotation(MyAspect.class).pointCut();
        this.pattern = Pattern.compile(reg);
    }

    @Override
    public int getOrder() {
        return order;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    @Override
    public boolean isMatch(Class<?> clazz, Method method) {
        return pattern.matcher(clazz.getName() + "." + method.getName()).find();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        AbstractAdvisor that = (AbstractAdvisor) o;
        return Objects.equals(aopObj, that.aopObj) &&
                Objects.equals(aopMethod, that.aopMethod);
    }

    @Override
    public int hashCode() {
        return Objects.hash(aopObj, aopMethod);
    }
}

Before增强

主要直接继承AbstractAdvisor,覆盖invoke方法即可

public class BeforeAdvisor extends AbstractAdvisor {

    public BeforeAdvisor(Object aopObj, Method aopMethod) {
        super(aopObj, aopMethod);
        setOrder(1);
    }

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Object[] args = {methodInvocation.getArguments()};//将Object[]转为数组,不然报错
        aopMethod.invoke(aopObj, args);
        return methodInvocation.proceed();
    }

}

After增强

与Before增强实现类似

public class AfterAdvisor extends AbstractAdvisor {
    public AfterAdvisor(Object aopObj, Method aopMethod) {
        super(aopObj, aopMethod);
        setOrder(2);
    }

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Object result = methodInvocation.proceed();
        Object[] args = {methodInvocation.getArguments()};//将Object[]转为数组,不然报错
        aopMethod.invoke(aopObj, args);
        return result;
    }
}

BeanPostProcessor扩展

上一遍文章讲到,AOP实现扩展了BeanPostProcessor,在Bean实例化后对Bean进行代理

@Component
public class MyAspectBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
    private ApplicationContext applicationContext;

    private List<Advisor> cacheAdvisors;//缓存提升性能

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        buildAdvisors();//构建增强

        Map<Method, List<Advisor>> methodListMap = getMatchAdvisor(bean);
        if (methodListMap.isEmpty())
            return bean;

        Enhancer enhancer = new Enhancer();//创建代理
        enhancer.setSuperclass(bean.getClass());
        enhancer.setCallback(new MethodInterceptorImp(methodListMap));
        return enhancer.create();
    }

    private void buildAdvisors() {
        if (cacheAdvisors != null) {
            return;
        }

        if (cacheAdvisors == null) {
            cacheAdvisors = new ArrayList<>();
        }

        Map<String, Object> map = applicationContext.getBeansWithAnnotation(MyAspect.class);

        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object aopObj = entry.getValue();
            Method[] methods = aopObj.getClass().getMethods();
            for (Method method : methods) {
                if (method.getName().equals("before")) {
                    Advisor advisor = new BeforeAdvisor(aopObj, method);
                    if (!cacheAdvisors.contains(advisor))
                        cacheAdvisors.add(advisor);
                } else if (method.getName().equals("after")) {
                    Advisor advisor = new AfterAdvisor(aopObj, method);
                    if (!cacheAdvisors.contains(advisor))
                        cacheAdvisors.add(advisor);
                }
            }

        }

    }

    private Map<Method, List<Advisor>> getMatchAdvisor(Object bean) {
        Class<?> clazz = bean.getClass();
        Method[] methods = clazz.getMethods();

        Map<Method, List<Advisor>> methodListMap = new HashMap<>();
        for (Method method : methods) {
            for (Advisor advisor : cacheAdvisors) {
                if (advisor.isMatch(clazz, method)) {
                    List<Advisor> advisors = methodListMap.get(method);
                    if (advisors == null) {
                        advisors = new ArrayList<>();
                        methodListMap.put(method, advisors);
                    }

                    advisors.add(advisor);
                }
            }

        }

        return methodListMap;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

Enhancer的回调实现

public class MethodInterceptorImp implements MethodInterceptor {

    private Map<Method, List<Advisor>> methodListMap;

    public MethodInterceptorImp(Map<Method, List<Advisor>> methodListMap) {
        this.methodListMap = methodListMap;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        List<Advisor> advisors = methodListMap.get(method);

        if (advisors == null){
            return proxy.invokeSuper(obj, args);
        }

        Collections.sort(advisors, new Comparator<Advisor>() {
            @Override
            public int compare(Advisor o1, Advisor o2) {
                return o2.getOrder() - o1.getOrder();
            }
        });

        MethodInvocation methodInvocation = new MethodInvocation(obj, method, args, proxy, advisors);

        return methodInvocation.proceed();
    }
}

链式调用

MethodInvocation主要是封装多个Advisor,形成递归链式调用

public class MethodInvocation implements Proceed{

    private Object target;

    private Method method;

    private Object[] arguments;

    private MethodProxy methodProxy;

    private List<Advisor> advisors;

    public MethodInvocation(Object target, Method method, Object[] arguments, MethodProxy proxy, List<Advisor> advisors) {
        this.target = target;
        this.method = method;
        this.arguments = arguments;
        this.methodProxy = proxy;
        this.advisors = advisors;
    }

    private int currentInterceptorIndex = -1;

    @Override
    public Object proceed() throws Throwable {
        if (currentInterceptorIndex == advisors.size() - 1){
            return methodProxy.invokeSuper(target, arguments);
        }

        ++currentInterceptorIndex;

        Advisor advisor = advisors.get(currentInterceptorIndex);

        return advisor.invoke(this);
    }

    public Object[] getArguments() {
        return arguments;
    }
}

Proceed接口

public interface Proceed {
    Object proceed() throws Throwable;
}

测试

Spring的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/

    <context:component-scan base-package="com.ydoing.spring.core.aop.customized"/>

</beans>

测试运行

public class App {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        FooService service = context.getBean(FooService.class);
        service.add(1, 2);

    }
}

输出

before增强,args[0]:1, args[1]:2
原有业务逻辑,result:3
after增强,args[0]:1, args[1]:2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值