动态代理--基础--04--AOP

动态代理–基础–04–AOP


代码位置

https://gitee.com/DanShenGuiZu/learnDemo/tree/master/动态代理/demo1

1、Aop中的代理

  1. Aop是对JDK代理和CGLIB代理做了一层封装,并且引入了AOP概念
  2. Aop严格的来说都是动态代理

1.1、Aop的注解

@Aspect
@advice
@joinpoint
@pointCut
@after
@before

1.2、原理

  • 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP,可以强制使用CGLIB实现AOP
  • 如果目标对象没有实现了接口,必须采用CGLIB实现AOP,spring会自动在JDK动态代理和CGLIB之间转换

1.2.1、如何强制使用CGLIB实现AOP?

  • 添加cglib库:SPRING_HOME/cglib/*.jar
  • 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

2、Aop 源码分析

2.1、代码

public class AOPTest {
    public static void main(String[] args) {
        ProxyFactory proxyFactory = new ProxyFactory(UserDao.class, new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("invoke 方法");
                return null;
            }
        });
        //设置优化
        proxyFactory.setOptimize(false);

        //得到代理对象
        Object proxy = proxyFactory.getProxy();
        UserDao userDao = (UserDao) proxy;
        userDao.addUser();
    }
}

2.2、源码分析

获取代理

  • 创建代理类
  • 获取代理

创建代理

  • 没有激活,
    • 设置激活状态是true
    • 设置监听功能加强
  • 获取aop代理工厂
  • 创建代理

获取默认代理工厂


创建aop代理

  • 进入if的条件
    • optimize(优化)=true:要优化
    • isProxyTargetClass=true:对具体类进行代理、
    • hasNoUserSuppliedProxyInterfaces=true:没有使用提供的代理接口(SpringProxy)
  • 进入if后
    • 代理目标不存在:aop配置异常
    • 代理目标是接口或者是Proxy的子类:返回jdk动态代理
    • 其他情况:返回glib动态代理
  • 其他情况:返回jdk动态代理

jdk动态代理源码

  • 获取代理接口数组
  • 查看方法代理接口中方法是不是equals,hashcode方法
  • 创建代理的class对象

JdkDynamicAopProxy中的就是最核心的方法invoke

/**
 * Implementation of {@code InvocationHandler.invoke}.
 * <p>Callers will see exactly the exception thrown by the target,
 * unless a hook method throws an exception.
 */
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	MethodInvocation invocation;
	Object oldProxy = null;
	boolean setProxyContext = false;

	TargetSource targetSource = this.advised.targetSource;
	Class targetClass = null;
	Object target = null;

	try {
		//是否实现equals和hashCode,没有实现就不代理。因为JDK代理会默认代理这两个方法
		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
			//没有实现equals方法就返回
			return equals(args[0]);
		}
		if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			//没有实现hashCode方法就返回
			return hashCode();
		}
		//不能代理adviser接口和子接口自身
		if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
				method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			 
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}

		Object retVal;
		//代理类和ThreadLocal绑定
		if (this.advised.exposeProxy) {
			// Make invocation available if necessary.
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}

		//获取目标对象
		target = targetSource.getTarget();
		if (target != null) {
			targetClass = target.getClass();
		}
		
		// 
		//得到拦截器链
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

	 
		//如果没有定义拦截器链。直接调用方法不进行代理
		if (chain.isEmpty()) {
			// 直接调用方法 
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
		}
		else {
			//创建ReflectiveMethodInvocation对象
			invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			//执行拦截器链。通过proceed递归调用 
			retVal = invocation.proceed();
		}

		//方法返回类型
		Class<?> returnType = method.getReturnType();
		if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
				!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
		 
			//如果返回值是this 直接返回代理对象本身
			retVal = proxy;
		} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
			throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
		}
		return retVal;
	}
	finally {
		if (target != null && !targetSource.isStatic()) {
			// Must have come from TargetSource.
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			// Restore old proxy.
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

ReflectiveMethodInvocation这个类的proceed()方法

负责递归调用所有的拦截的织入

	@Override
	@Nullable
	public Object proceed() throws Throwable {
		//	list的索引从-1开始。 
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {\
		//所有interceptor都被执行完了 ,直接执行原方法
			return invokeJoinpoint();
		}
		//获取拦加强方法(是before或after等织入,不受在list中的位置影响)
		Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
				
		 //........
			// 调用我们实现接口(MethodInterceptor)的invoke方法
			//  
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

要实现织入,只要控制织入的代码和调用proceed方法的位置

在Spring中的before织入

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

	private MethodBeforeAdvice advice;

	public Object invoke(MethodInvocation mi) throws Throwable {
		//调用before实际代码
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
		//继续迭代
		return mi.proceed();
	}

afterRuturning是这样实现的:

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

    private final AfterReturningAdvice advice;

    public Object invoke(MethodInvocation mi) throws Throwable {
        Object retVal = mi.proceed();
        //只要控制和mi.proceed()调用的位置关系就可以实现任何状态的织入效果
        this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
        return retVal;
    }

包含上述一个before织入和一个afterReturning织入的流程图:

利用迭代的思想很简单实现了链式调用

public interface MethodInterceptor {

    Object invoke(Invocation invocation);


    public static class beforeMethodInterceptor implements MethodInterceptor{
       
       

        @Override
        public Object invoke(Invocation invocation) {
            System.out.println("开始前方法");

            return invocation.proceed();
        }
    }
    public static class AfterRuturningMethodInterceptor implements MethodInterceptor{
        @Override
        public Object invoke(Invocation invocation) {
            Object proceed = invocation.proceed();
            System.out.println("结束后方法");
            return proceed;
        }
    }
    
    }
}


public interface Invocation {

    Object proceed();

    public static class MethodInvocation implements Invocation{
        private List<MethodInterceptor> list;
        private int index=-1;
        private int ListSize=0;
        public MethodInvocation(List<MethodInterceptor> list) {
            this.list=list;
            ListSize=list.size();
        }

        @Override
        public Object proceed() {
            if(index==ListSize-1){
                System.out.println("执行方法实体");
                return "返回值";
            }
            MethodInterceptor methodInterceptor = list.get(++index);
			//递归调用方法
            return  methodInterceptor.invoke(this);
        }
    }
}

3、AOP的简单实现

3.1、设计

3.1.1、核心思路

  • 维护一个映射表MAP(切点方法,增强方法列表)
  • 使用cglib对切点进行增强。
  • 返回cglib的代理实例

3.1.2、细节

  1. 扫描要被增强的bean
  2. 扫描所有切面
  3. 构建映射表MAP(切点方法,增强方法列表)
  4. 构建bean容器,该容器包含切面信息

3.2、代码

在这里插入图片描述

package feizhou.demo1.business.demo.myAop.annotation;

/**
 * 
 * 切点类型
 * @author  <a href="920786312@qq.com">周飞</a>
 * @since 2024/4/28 10:24
 */
public enum MyPointCutType {
  //前置通知
  BEFORE,
  //后置通知
  AFTER,
}

package feizhou.demo1.business.demo.myAop.annotation;

import org.springframework.core.annotation.AliasFor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义切点注解
 *
 * @author <a href="920786312@qq.com">周飞</a>
 * @return
 * @since 2024/4/28 10:24
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyPointCut {



    /**
     * 包路径的切点表达式
     * @param
     * @return java.lang.String[]
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/5/1 22:16
     */
    String[] packagePath() default {};

    //切点类型
    MyPointCutType type();
}

package feizhou.demo1.business.demo.myAop.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义切面注解
 * 定义在类上,那么该类就是一个切面,切面有定义对那些方法进行增强
 * @author <a href="920786312@qq.com">周飞</a>
 * @since 2024/4/27 22:51
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAspect {
}

package feizhou.demo1.business.demo.myAop.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义实例化注解
 * 定义在类上,那么这个类就是加入到AOP增强的bean 容器中
 * @author  <a href="920786312@qq.com">周飞</a>
 * @since 2024/4/27 22:55
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyComponent {
}

package feizhou.demo1.business.demo.myAop.example;


import feizhou.demo1.business.demo.myAop.annotation.MyAspect;
import feizhou.demo1.business.demo.myAop.annotation.MyComponent;
import feizhou.demo1.business.demo.myAop.annotation.MyPointCut;
import feizhou.demo1.business.demo.myAop.annotation.MyPointCutType;

@MyAspect
@MyComponent
public class MyBeanAspect {

    /**
     * 定义扫描包路径和切点类型为前置通知
     *
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/4/28 10:29
     */
    // 前置通知
    @MyPointCut(type = MyPointCutType.BEFORE,
            packagePath = {"public int feizhou.demo1.business.demo.myAop.example.Teacher.getName(java.lang.String)",
                    "public void feizhou.demo1.business.demo.myAop.example.User.addUser(java.lang.String, int)"})


    public static void logBefore() {
        System.out.println("前置通知--->静态方法");
    }

    // 后置通知
    @MyPointCut(type = MyPointCutType.AFTER,
            packagePath = {"public int feizhou.demo1.business.demo.myAop.example.Teacher.getName(java.lang.String)",
                    "public void feizhou.demo1.business.demo.myAop.example.User.addUser(java.lang.String, int)"})
    public static void logAfter() {
        System.out.println("后置通知--->静态方法");
    }

    // 后置通知
    @MyPointCut(type = MyPointCutType.AFTER,
            packagePath = {"public int feizhou.demo1.business.demo.myAop.example.Teacher.getName(java.lang.String)",
                    "public void feizhou.demo1.business.demo.myAop.example.User.addUser(java.lang.String, int)"})
    public void logAfter2() {
        System.out.println("后置通知--->非静态方法");
    }

}

package feizhou.demo1.business.demo.myAop.example;

import feizhou.demo1.business.demo.myAop.annotation.MyComponent;

@MyComponent
public class Teacher {

  public void getName(String name) {
    System.out.println("当前老师名称是:" + name);
  }

}

package feizhou.demo1.business.demo.myAop.example;


import feizhou.demo1.business.demo.myAop.annotation.MyComponent;

@MyComponent
public class User {

    public String addUser(String name, int age) {
        String s = "新增用户:" + name + ",年龄:" + age;
        System.out.println(s);
        return s;
    }

}

package feizhou.demo1.business.demo.myAop;


import feizhou.demo1.business.demo.myAop.annotation.MyPointCut;
import feizhou.demo1.business.demo.myAop.annotation.MyPointCutType;
import lombok.Data;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Map;

/**
 * @Description 增强bean
 * @Author feizhou
 * @Date 2024/5/1  14:46
 * @Verson 1.0
 **/
@Data
public class ExpandBean {

    //切点class类对象
    private Class<?> pointCutClazz;
    //切面class类对象
    private Class<?> aspectClazz;

    /**
     * 被增强的实例,这个实例可能被增强,也可能没有被增强
     *
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/5/1 14:47
     */
    private Object instance;
    /**
     * 扩展类对应的切面
     *
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/5/1 20:25
     */
    private ExpandBeanAspect expandBeanAspect;

    public ExpandBean(Class<?> pointCutClazz, Class<?> aspectClazz) {//构造方法
        this.pointCutClazz = pointCutClazz;
        this.aspectClazz = aspectClazz;
    }

    /**
     * cglib 动态代理,实现MethodInterceptor方法
     *
     * @author <a href="920786312@qq.com">周飞</a>
     * @return
     * @since 2024/5/1 15:33
     */
    // Method interceptor for bean proxy class.
    //代理bean的获取
    private static class BeanProxyInterceptor implements MethodInterceptor {
        ExpandBeanFactory beanFactory;
        ExpandBeanAspect expandBeanAspect;

        public BeanProxyInterceptor(ExpandBeanFactory beanFactory, ExpandBeanAspect expandBeanAspect) {
            this.beanFactory = beanFactory;
            this.expandBeanAspect = expandBeanAspect;
        }

        private void invokeAspectMethod(Method method) throws Exception {
            if (Modifier.isStatic(method.getModifiers())) {//静态方法
                method.invoke(null);
            } else {//非静态方法,无参构造
                method.invoke(beanFactory.getBean(method.getDeclaringClass()));
            }
        }

        @Override
        public Object intercept(Object obj, Method method, Object[] args,
                                MethodProxy proxy) throws Throwable {

            ExpandBeanAspect.AspectMethods aspects = expandBeanAspect.getPointCutAspects().get(method);
            if (aspects == null) {
                // No aspect for this method.
                return proxy.invokeSuper(obj, args);
            }

            //前置通知方法
//            for (Map.Entry<Class, ExpandBeanAspect.AspectMethods> entry : aspects.entrySet()) {
//                Class aspectBeanId = entry.getKey();
//                ExpandBeanAspect.AspectMethods aspectMethods = entry.getValue();
            // Invoke aspect "before" methods.
            for (Method m : aspects.beforeMethods) {
                invokeAspectMethod(m);
            }
//            }

            // 业务方法
            Object re = proxy.invokeSuper(obj, args);
//            //后置通知方法

            // Invoke aspect "after" methods.
            for (Method m : aspects.afterMethods) {
                invokeAspectMethod(m);
            }


            return re;
        }
    }

    /**
     * 获取bean的增强实例
     *
     * @param beanFactory
     * @return java.lang.Object
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/5/1 16:16
     */
    public Object getInstance(ExpandBeanFactory beanFactory) throws Exception {
        //如果就返回
        if (this.instance != null) {
            return this.instance;
        }

        synchronized (this) {
            if (this.instance != null) {
                return this.instance;
            }

            //如果切面不存在
            if (expandBeanAspect == null) {
                // 如果切面不存在,通过反射返回一个简单类
                this.instance = pointCutClazz.getConstructor(new Class[]{}).newInstance();
            } else {
                // cglib 代理增强
                Enhancer eh = new Enhancer();
                eh.setSuperclass(pointCutClazz);
                eh.setCallback(new BeanProxyInterceptor(beanFactory, expandBeanAspect));
                //返回代理类
                this.instance = eh.create();
            }
            return this.instance;
        }
    }

    /**
     * 添加切面方法
     *
     * @param pointcutMethod 切点方法
     * @param myPointCut     切点注解
     * @param aspectMethod   切面方法
     * @return void
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/5/1 17:55
     */
    public void addAspectMethod(Method pointcutMethod, MyPointCut myPointCut, Method aspectMethod) {

        Map<Method, ExpandBeanAspect.AspectMethods> pointCutAspects = expandBeanAspect.getPointCutAspects();
        // Find pointcut method.
        ExpandBeanAspect.AspectMethods aspectMethods = pointCutAspects.get(pointcutMethod);


        if (aspectMethods == null) {
            //切面方法不存在,创建切面方法
            aspectMethods = new ExpandBeanAspect.AspectMethods();
            pointCutAspects.put(pointcutMethod, aspectMethods);
        }

        //补充切面方法的数据
        if (myPointCut.type() == MyPointCutType.BEFORE) {
            aspectMethods.beforeMethods.add(aspectMethod);
        } else if (myPointCut.type() == MyPointCutType.AFTER) {
            aspectMethods.afterMethods.add(aspectMethod);
        }
    }
}

package feizhou.demo1.business.demo.myAop;


import feizhou.demo1.business.demo.myAop.annotation.MyPointCut;
import feizhou.demo1.business.demo.myAop.annotation.MyPointCutType;
import lombok.Getter;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 扩展bean的切面
 * 一个扩展bean 只有一个切面
 *
 * @author <a href="920786312@qq.com">周飞</a>
 * @since 2024/4/28 14:13
 */
public class ExpandBeanAspect {
    /**
     * 定义切点方法、对应的切面方法
     * Map from pointcut method to aspects. Each aspect is a also a map, from aspect bean to aspect
     * Map<切点方法,Map<beanId,切面方法>>
     *
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/4/29 12:29
     */
    @Getter
    private Map<Method, AspectMethods> pointCutAspects = new HashMap<>();

    /**
     * 切面方法
     *
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/4/29 12:29
     */
    public static class AspectMethods {
        public List<Method> beforeMethods = new ArrayList<>();
        public List<Method> afterMethods = new ArrayList<>();
    }


}

package feizhou.demo1.business.demo.myAop;

import com.google.common.reflect.ClassPath;
import feizhou.demo1.business.demo.myAop.annotation.MyAspect;
import feizhou.demo1.business.demo.myAop.annotation.MyComponent;
import feizhou.demo1.business.demo.myAop.annotation.MyPointCut;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 扩展bean的工厂
 *
 * @author <a href="920786312@qq.com">周飞</a>
 * @since 2024/4/27 22:49
 */
public class ExpandBeanFactory {

    //bean容器
    public Map<Class, ExpandBean> beans = new HashMap();


    public ExpandBeanFactory(String[] packages) {//构造方法
        scanPackages(packages);
    }

    /**
     * 获取bean,这个bean是增强的bean
     *
     * @return java.lang.Object
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/4/27 22:49
     */
    public Object getBean(Class clazz) throws Exception {
        ExpandBean expandBean = beans.get(clazz);
        if (expandBean != null) {
            return expandBean.getInstance(this);
        } else {
            throw new RuntimeException("No such bean: " + clazz);
        }
    }

    /**
     * 扫描包
     *
     * @param packages
     * @return void
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/4/27 22:51
     */
    private void scanPackages(String[] packages) {
        for (String pkg : packages) {
            scanBeansInPackage(pkg);
        }
    }

    /**
     * 扫描包
     *
     * @param pkg 包路径
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/5/1 21:50
     */
    private void scanBeansInPackage(String pkg) {
        ClassPath cp;
        try {
            cp = ClassPath.from(getClass().getClassLoader());
        } catch (IOException e) {
            e.printStackTrace();
            //有异常就退出
            return;
        }
        //先加载对应的bean
        for (ClassPath.ClassInfo ci : cp.getTopLevelClasses(pkg)) {
            //加载类
            Class<?> clazz = ci.load();
            // 加载有MyComponent注解的类到bean 容器里面去
            Annotation componentAnnotation = clazz.getAnnotation(MyComponent.class);
            if (componentAnnotation != null) {
                // Add new Bean.
                beans.put(clazz, new ExpandBean(clazz, null));
            }
        }
        //再加载切面
        for (ClassPath.ClassInfo ci : cp.getTopLevelClasses(pkg)) {
            //加载类
            Class<?> clazz = ci.load();

            // 加载有MyAspect注解的类到切面中
            Annotation componentAnnotation = clazz.getAnnotation(MyAspect.class);
            if (componentAnnotation != null) {
                //切面方法
                for (Method aspectMethod : clazz.getMethods()) {
                    addBeanAspects(aspectMethod);
                }
            }
        }
    }

    /**
     * 添加切面
     *
     * @param aspectMethod
     * @return void
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/5/1 21:43
     */
    private void addBeanAspects(Method aspectMethod) {

        // 获取切点注解
        MyPointCut myPointCut = aspectMethod.getDeclaredAnnotation(MyPointCut.class);

        if (myPointCut != null) {
            //获取切点方法
            for (Method pointCutMethod : parsePointCutExpr(myPointCut.packagePath())) {
                //获取切点类名称
                Class pointCutClazz = pointCutMethod.getDeclaringClass();

                ExpandBean expandBean = beans.get(pointCutClazz);
                //获取切面
                ExpandBeanAspect expandBeanAspect = expandBean.getExpandBeanAspect();
                if (expandBeanAspect == null) { //切面不存在就创建
                    expandBeanAspect = new ExpandBeanAspect();
                    //切点的beanId
                    expandBean.setExpandBeanAspect(expandBeanAspect);
                    expandBean.setAspectClazz(aspectMethod.getDeclaringClass());
                }
                //切面添加切点方法
                expandBean.addAspectMethod(pointCutMethod, myPointCut, aspectMethod);
            }
        }

    }

    /**
     * 解析并获取切点方法
     *
     * @param packagePaths 包路径数组
     * @return java.util.List<java.lang.reflect.Method>
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2024/5/1 21:49
     */
    private List<Method> parsePointCutExpr(String[] packagePaths) {
        List<Method> result = new ArrayList<Method>();

        //正则表达式
        Pattern r = Pattern.compile("^public \\s*[\\w\\$]+ \\s*(([\\w\\$]+\\.)*([\\w\\$]+))\\.([\\w\\$]+)\\s*\\((.*)\\)$");

        //以分号分割切点
        for (String point : packagePaths) {
            Matcher m = r.matcher(point.trim());
            if (!m.find()) {
                System.out.println("Can't parse cut point expression: " + point);
                continue;
            }

            String pointCutClassPath = m.group(1);
            String pointCutMethodName = m.group(4);
            String pointCutMethodArgsList = m.group(5);

            try {
                //class
                Class<?> clazz = Class.forName(pointCutClassPath);
                //方法参数数组
                String[] argTypeListStr = pointCutMethodArgsList.split(",");
                //参数类型的class数组
                Class[] argTypes = new Class[argTypeListStr.length];
                for (int i = 0; i < argTypeListStr.length; i++) {
                    argTypes[i] = getArgClass(argTypeListStr[i].trim());
                }
                result.add(clazz.getMethod(pointCutMethodName, argTypes));
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                continue;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
                continue;
            }
        }
        return result;
    }

    //返回参数类型的class对象
    private Class getArgClass(String str) throws ClassNotFoundException {
        if (str.equals("int")) {
            return int.class;
        } else if (str.equals("long")) {
            return long.class;
        } else if (str.equals("short")) {
            return short.class;
        } else if (str.equals("float")) {
            return float.class;
        } else if (str.equals("double")) {
            return double.class;
        } else if (str.equals("byte")) {
            return byte.class;
        } else if (str.equals("char")) {
            return char.class;
        } else if (str.equals("boolean")) {
            return boolean.class;
        } else {
            return Class.forName(str);
        }
    }
}

package feizhou.demo1.business.demo.myAop;

/**
 * @ClassName: AOPTest
 * @Description 请描述下该类是做什么的
 * @Author feizhou
 * @Date 2024/4/27  21:37
 * @Verson 1.0
 **/

import feizhou.demo1.business.demo.myAop.example.Teacher;
import feizhou.demo1.business.demo.myAop.example.User;

import java.util.*;
import java.lang.reflect.*;

public class AOPTest {

    public static void main(String[] args) throws Exception {
        testBeanFactory();
    }

    public static void testBeanFactory() throws Exception {
        //通过包路径获取工厂
        ExpandBeanFactory factory = new ExpandBeanFactory(new String[]{"feizhou.demo1.business.demo.myAop.example"});


        for (Map.Entry<Class, ExpandBean> entry1 : factory.beans.entrySet()) {

            ExpandBean expandBean = entry1.getValue();
            System.out.println("切点类: " + expandBean.getPointCutClazz());
            System.out.println("  切面类: " + expandBean.getAspectClazz());

            ExpandBeanAspect expandBeanAspect = expandBean.getExpandBeanAspect();

            Map<Method, ExpandBeanAspect.AspectMethods> pointCutAspects=null;
            if(expandBeanAspect!=null){
                pointCutAspects = expandBeanAspect.getPointCutAspects();
            }
            if(pointCutAspects==null){
                continue;
            }
            for (Map.Entry<Method, ExpandBeanAspect.AspectMethods> entry2 : pointCutAspects.entrySet()) {

                System.out.println("  切点方法: " + entry2.getKey().getName());

                for (Method method : entry2.getValue().beforeMethods) {
                    System.out.println("      切面before方法: " + method.getName());
                }
                for (Method method : entry2.getValue().afterMethods) {
                    System.out.println("      切面after方法: " + method.getName());
                }

            }
        }
        System.out.println();
        System.out.println("---------teacher.getName------------");
        Teacher teacher = (Teacher) factory.getBean(Teacher.class);
        teacher.getName("小周");


        System.out.println();
        System.out.println("----------user.addUser-----------");
        User user = (User) factory.getBean(User.class);
        user.addUser("小明", 100);


    }

}

输出:
切点类: class feizhou.demo1.business.demo.myAop.example.Teacher
  切面类: class feizhou.demo1.business.demo.myAop.example.MyBeanAspect
  切点方法: getName
      切面before方法: logBefore
      切面after方法: logAfter
      切面after方法: logAfter2
切点类: class feizhou.demo1.business.demo.myAop.example.MyBeanAspect
  切面类: null
切点类: class feizhou.demo1.business.demo.myAop.example.User
  切面类: class feizhou.demo1.business.demo.myAop.example.MyBeanAspect
  切点方法: addUser
      切面before方法: logBefore
      切面after方法: logAfter
      切面after方法: logAfter2

---------teacher.getName------------
前置通知--->静态方法
当前老师名称是:小周
后置通知--->静态方法
后置通知--->非静态方法

----------user.addUser-----------
前置通知--->静态方法
新增用户:小明,年龄:100
后置通知--->静态方法
后置通知--->非静态方法

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值