代理
package com.xtq.aop.proxy;import com.xtq.annotations.After;
import com.xtq.annotations.Before;
import com.xtq.annotations.Pointcut;import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;public class AOPProxy {// 创建代理对象public static <T> T createProxy(Class<T> targetInterface, Object targetClassInstance, List<Object> aspects) {return (T) Proxy.newProxyInstance(targetInterface.getClassLoader(),new Class<?>[]{targetInterface},new AOPInvocationHandler(targetClassInstance, aspects));}
}
调用类
package com.xtq.aop.proxy;import com.xtq.annotations.After;
import com.xtq.annotations.Before;
import com.xtq.annotations.Pointcut;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class AOPInvocationHandler implements InvocationHandler {private final Object target;private final List<Object> aspects;public AOPInvocationHandler(Object targetClassInstance, List<Object> aspects) {this.target = targetClassInstance;this.aspects = aspects;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 1. 执行 @Before 注解的切面方法invokeBefore(method);// 2. 执行目标方法Object result = method.invoke(target, args);// 3. 执行 @After 注解的切面方法invokeAfter(method);return result;}private void invokeBefore(Method method) throws InvocationTargetException, IllegalAccessException {for (Object aspect : aspects) {// 遍历切面类的方法for (Method aspectMethod : aspect.getClass().getDeclaredMethods()) {// 判断是否存在 @Pointcut 注解if (aspectMethod.isAnnotationPresent(Pointcut.class)) {String pointcutExpression = aspectMethod.getAnnotation(Pointcut.class).value();// 如果切入点表达式与当前方法匹配,则执行 @Before 增强方法if (matchesPointcut(pointcutExpression, method)) {for (Method beforeMethod : aspect.getClass().getDeclaredMethods()) {if (beforeMethod.isAnnotationPresent(Before.class)) {System.out.println("代理执行的 Aspect Before: " + beforeMethod.getName());beforeMethod.invoke(aspect); // 执行 @Before 增强方法}}}}}}}private void invokeAfter(Method method) throws InvocationTargetException, IllegalAccessException {for (Object aspect : aspects) {// 遍历切面类的方法for (Method aspectMethod : aspect.getClass().getDeclaredMethods()) {// 判断是否存在 @Pointcut 注解if (aspectMethod.isAnnotationPresent(Pointcut.class)) {String pointcutExpression = aspectMethod.getAnnotation(Pointcut.class).value();// 如果切入点表达式与当前方法匹配,则执行 @After 增强方法if (matchesPointcut(pointcutExpression, method)) {for (Method afterMethod : aspect.getClass().getDeclaredMethods()) {if (afterMethod.isAnnotationPresent(After.class)) {System.out.println("代理执行的 Aspect After: " + afterMethod.getName());afterMethod.invoke(aspect); // 执行 @After 增强方法}}}}}}}private boolean matchesPointcut(String pointcutExpression, Method method) {// 简单解析 execution(* UserService.addUser(..)) 格式的表达式Pattern pattern = Pattern.compile("execution\\(\\*\\s*(\\S+)\\.(\\S+)\\(.*\\)\\)");Matcher matcher = pattern.matcher(pointcutExpression);if (matcher.matches()) {String className = matcher.group(1); // 类名String methodName = matcher.group(2); // 方法名// 获取当前方法的类名和方法名String targetClassName = method.getDeclaringClass().getSimpleName();String targetMethodName = method.getName();// 判断是否匹配return targetMethodName.equals(methodName) && targetClassName.equals(className);}return false;}}
切面类aspect
package com.xtq.aop;import com.xtq.annotations.After;
import com.xtq.annotations.Before;
import com.xtq.annotations.Pointcut;public class Aspect {// 定义切入点@Pointcut("execution(* UserService.addUser(..))")public void doSomethingPointcut() {// 这里可以定义切入点的匹配规则}@Before("doSomethingPointcut")public void beforeMethod() {System.out.println("被代理调用得到的Aspect: Before method executed.");}@After("doSomethingPointcut")public void afterMethod() {System.out.println("被代理调用的得到的Aspect: After method executed.");}
}
IOC容器
package com.xtq.container;import java.util.HashMap;
import java.util.Map;public class IoCContainer {private Map<Class<?>, Object> beans = new HashMap<>();// 注册Bean:根据接口和实现类注册public <T> void registerBean(Class<T> interfaceClass, Class<? extends T> clazz) {try {T instance = clazz.getDeclaredConstructor().newInstance();beans.put(interfaceClass, instance);} catch (Exception e) {e.printStackTrace();}}// 获取Bean实例public <T> T getBean(Class<T> interfaceClass) {return (T) beans.get(interfaceClass);}
}
Main
package com.xtq;import com.xtq.aop.Aspect;
import com.xtq.aop.proxy.AOPProxy;
import com.xtq.container.IoCContainer;
import com.xtq.service.UserService;
import com.xtq.service.UserServiceImpl;import java.util.ArrayList;
import java.util.List;public class Main {public static void main(String[] args) {// 1. 创建 IOC 容器IoCContainer container = new IoCContainer();// 注册接口和实现类container.registerBean(UserService.class, UserServiceImpl.class);// 获取实际的业务实现类UserService userService = container.getBean(UserService.class);// 2. 创建切面列表(目前没有切面,可以传递空列表)List<Object> aspects = new ArrayList<>();Aspect aspect = new Aspect();aspects.add(aspect);// 3. 创建AOP代理对象UserService proxyService = AOPProxy.createProxy(UserService.class, userService, aspects);// 4. 调用代理方法,测试AOP功能proxyService.addUser("代理过的xtq");System.out.println("===============================================================");proxyService.deleteUser("没有代理过xtq");}
}