福建住房和城乡建设厅网站上市公司网站建设分析评价
2026/1/29 9:47:32 网站建设 项目流程
福建住房和城乡建设厅网站,上市公司网站建设分析评价,怎样讲卖灯的网站做的好,深圳门户网站建设✅ 手撸 Spring 简易版 AOP 一、核心目标 在已有 IOC 容器基础上#xff0c;新增 AOP 能力#xff0c;包含#xff1a; 自定义注解 MyAspect、MyBefore、MyAfter#xff1b;切面类识别与注册#xff1b;使用 JDK 动态代理对目标 Bean 进行代理#xff1b;支持方法执行前/…✅ 手撸 Spring 简易版 AOP一、核心目标在已有 IOC 容器基础上新增 AOP 能力包含自定义注解MyAspect、MyBefore、MyAfter切面类识别与注册使用 JDK 动态代理对目标 Bean 进行代理支持方法执行前/后通知Before / After与 IOC 容器无缝集成依赖注入 AOP 代理。 注意为简化仅支持接口代理JDK Proxy不支持 CGLIB无接口类。二、完整实现代码步骤 1定义 AOP 注解import java.lang.annotation.*; // 标记切面类 Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) public interface MyAspect { } // 前置通知 Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface MyBefore { String value(); // 切点表达式如 com.example.service.UserServiceImpl.getUser } // 后置通知 Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface MyAfter { String value(); } 切点表达式简化为全限定方法名如org.example.service.UserServiceImpl.getUser不使用 AspectJ 表达式。步骤 2扩展 MyApplicationContext支持 AOP在原有 IOC 容器中增加 AOP 处理逻辑。import java.lang.reflect.*; import java.util.*; // 新增导入 import java.util.concurrent.ConcurrentHashMap; public class MyApplicationContext { private MapString, MyBeanDefinition beanDefinitionMap new HashMap(); private MapString, Object singletonObjects new ConcurrentHashMap(); // 改为线程安全 private Class? configClass; // 新增存储切面信息 { 切点方法全名 - 切面对象 } private MapString, Object aspectBeans new HashMap(); // 存储 Before 方法 private MapString, Method beforeAdviceMethods new HashMap(); // 存储 After 方法 private MapString, Method afterAdviceMethods new HashMap(); public MyApplicationContext(Class? configClass) { this.configClass configClass; scanAndRegisterBeanDefinitions(); registerAspects(); // 新增注册切面 instantiateSingletons(); } // 原有方法保持不变scanAndRegisterBeanDefinitions, recursiveScan 等 // 新增扫描并注册所有 MyAspect 切面 private void registerAspects() { for (Map.EntryString, MyBeanDefinition entry : beanDefinitionMap.entrySet()) { Class? clazz entry.getValue().getBeanClass(); if (clazz.isAnnotationPresent(MyAspect.class)) { String beanName entry.getKey(); Object aspectBean createBean(beanName, entry.getValue()); // 先实例化切面无依赖注入 aspectBeans.put(beanName, aspectBean); // 解析切面中的 MyBefore / MyAfter for (Method method : clazz.getDeclaredMethods()) { if (method.isAnnotationPresent(MyBefore.class)) { MyBefore before method.getAnnotation(MyBefore.class); String pointcut before.value(); beforeAdviceMethods.put(pointcut, method); } if (method.isAnnotationPresent(MyAfter.class)) { MyAfter after method.getAnnotation(MyAfter.class); String pointcut after.value(); afterAdviceMethods.put(pointcut, method); } } } } } // 重写 createBean如果目标 Bean 有切面则返回代理对象 private Object createBean(String beanName, MyBeanDefinition beanDefinition) { Class? beanClass beanDefinition.getBeanClass(); try { Object beanInstance beanClass.getDeclaredConstructor().newInstance(); populateBean(beanInstance); // 依赖注入 // 检查是否需要 AOP 代理 if (needsProxy(beanClass)) { return createProxy(beanInstance, beanClass); } return beanInstance; } catch (Exception e) { throw new RuntimeException(创建 Bean 失败 beanName, e); } } // 判断是否需要代理只要存在匹配的切点就代理 private boolean needsProxy(Class? targetClass) { for (String pointcut : beforeAdviceMethods.keySet()) { if (pointcut.startsWith(targetClass.getName())) { return true; } } for (String pointcut : afterAdviceMethods.keySet()) { if (pointcut.startsWith(targetClass.getName())) { return true; } } return false; } // 创建 JDK 动态代理 private Object createProxy(Object target, Class? targetClass) { return Proxy.newProxyInstance( targetClass.getClassLoader(), targetClass.getInterfaces(), // 必须有接口 new MyInvocationHandler(target, targetClass) ); } // 自定义 InvocationHandler private class MyInvocationHandler implements InvocationHandler { private Object target; private Class? targetClass; public MyInvocationHandler(Object target, Class? targetClass) { this.target target; this.targetClass targetClass; } Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String fullMethodName targetClass.getName() . method.getName(); // 执行 MyBefore if (beforeAdviceMethods.containsKey(fullMethodName)) { Method beforeMethod beforeAdviceMethods.get(fullMethodName); String aspectBeanName findAspectBeanForMethod(beforeMethod); Object aspect aspectBeans.get(aspectBeanName); beforeMethod.setAccessible(true); beforeMethod.invoke(aspect); } // 执行目标方法 Object result method.invoke(target, args); // 执行 MyAfter if (afterAdviceMethods.containsKey(fullMethodName)) { Method afterMethod afterAdviceMethods.get(fullMethodName); String aspectBeanName findAspectBeanForMethod(afterMethod); Object aspect aspectBeans.get(aspectBeanName); afterMethod.setAccessible(true); afterMethod.invoke(aspect); } return result; } // 辅助根据通知方法反推切面 Bean 名称 private String findAspectBeanForMethod(Method adviceMethod) { Class? aspectClass adviceMethod.getDeclaringClass(); for (Map.EntryString, Object entry : aspectBeans.entrySet()) { if (entry.getValue().getClass() aspectClass) { return entry.getKey(); } } throw new RuntimeException(未找到切面对应的 Bean aspectClass.getName()); } } // 原有方法populateBean, getBean, 工具方法等保持不变 // 此处省略与你提供的代码一致 }⚠️ 注意目标类必须实现接口否则Proxy.newProxyInstance会失败。步骤 3编写测试用例1. 定义接口和实现类public interface UserService { void getUser(); } MyComponent(userService) public class UserServiceImpl implements UserService { MyAutowired private UserDao userDao; Override public void getUser() { userDao.queryUser(); System.out.println(业务逻辑获取用户); } }2. 编写切面类MyAspect MyComponent(logAspect) public class LogAspect { MyBefore(com.example.spring6.aop.demo.UserServiceImpl.getUser) public void beforeGetUser() { System.out.println(【AOP 前置通知】准备调用 getUser 方法); } MyAfter(com.example.spring6.aop.demo.UserServiceImpl.getUser) public void afterGetUser() { System.out.println(【AOP 后置通知】getUser 方法执行完毕); } }3. 配置类同 IOCMyConfiguration(scanPackage org.example.spring6.aop) public class AppConfig { }4. 测试主类public class MyAopTest { public static void main(String[] args) { MyApplicationContext context new MyApplicationContext(AppConfig.class); UserService userService (UserService) context.getBean(userService); userService.getUser(); } }运行结果【AOP 前置通知】准备调用 getUser 方法 Spring 6.x 简易 IOC查询用户信息 业务逻辑获取用户 【AOP 后置通知】getUser 方法执行完毕✅ 成功实现 AOP 通知三、简易 AOP vs Spring 6.x 对比简易 AOP 组件Spring 6.x 原生组件说明MyAspect/MyBeforeAspect/Before切面与通知注解MyInvocationHandlerJdkDynamicAopProxyJDK 动态代理处理器aspectBeansadviceMethodsAdvisorRegistryPointcutAdvisor切面注册与匹配手动解析切点PointcutExpressionAspectJExpressionPointcutSpring 使用 AspectJ 表达式关注我每天5分钟带你从 Java 小白变身编程高手 点赞 关注私信 ”AOP源码“获取手撸源码让更多小伙伴一起进步

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询