├── .gitignore ├── README.md └── src └── com └── mafei ├── spring ├── BeanDefinition.java ├── DisposableBeanAdapter.java ├── MaFeiApplicationContext.java ├── anno │ ├── Autowired.java │ ├── Component.java │ ├── ComponentScan.java │ ├── Lazy.java │ └── Scope.java ├── aop │ ├── AnnotationAwareAspectJAutoProxyCreator.java │ ├── AspectInstanceFactory.java │ ├── AspectJAdvisorFactory.java │ ├── DefaultAspectJAdvisorFactory.java │ ├── PrototypeAspectInstanceFactory.java │ ├── SingletonAspectInstanceFactory.java │ ├── advisor │ │ ├── Advice.java │ │ ├── Advisor.java │ │ ├── AspectJExpressionPointcut.java │ │ ├── CommonAdvice.java │ │ ├── DefaultMethodInvocation.java │ │ ├── DefaultPointcutAdvisor.java │ │ ├── Interceptor.java │ │ ├── Joinpoint.java │ │ ├── MethodInterceptor.java │ │ ├── MethodInvocation.java │ │ ├── MethodMatcher.java │ │ ├── Pointcut.java │ │ └── joinpoint │ │ │ ├── JoinPoint.java │ │ │ ├── MethodInvocationProceedingJoinPoint.java │ │ │ └── ProceedingJoinPoint.java │ ├── anno │ │ ├── After.java │ │ ├── AfterAdvice.java │ │ ├── AfterReturning.java │ │ ├── AfterReturningAdvice.java │ │ ├── AfterThrowing.java │ │ ├── AfterThrowingAdvice.java │ │ ├── Around.java │ │ ├── AroundAdvice.java │ │ ├── Aspect.java │ │ ├── Before.java │ │ └── BeforeAdvice.java │ ├── proxy │ │ ├── AopContext.java │ │ ├── AopProxy.java │ │ ├── JdkDynamicAopProxy.java │ │ ├── LazyInjectTargetSource.java │ │ ├── ObjenesisCglibAopProxy.java │ │ ├── ProxyFactory.java │ │ ├── SingletonTargetSource.java │ │ └── TargetSource.java │ └── util │ │ └── AopUtils.java ├── core │ ├── OrderComparator.java │ ├── Ordered.java │ └── PriorityOrdered.java └── interfaces │ ├── ApplicationContextAware.java │ ├── BeanNameAware.java │ ├── BeanPostProcessor.java │ ├── DisposableBean.java │ ├── InitializingBean.java │ ├── ObjectFactory.java │ └── SmartInstantiationAwareBeanPostProcessor.java └── test ├── AppConfig.java ├── MyAspect.java ├── MyAspect2.java ├── OrderService.java ├── PostInterface.java ├── PostService.java ├── Test.java ├── TestBeanPostProcessor.java ├── UserInterface.java ├── UserService.java └── circular_references ├── A.java ├── AppConfig.java ├── B.java ├── C.java ├── D.java ├── MyAspect.java ├── MyInterface.java └── Test.java /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring-impl 2 | 学习了 Spring 原理后写的一个 Spring 简单实现。 3 | 4 | 主要实现了 IOC 和 AOP 功能 5 | 6 | ## IOC 7 | ### Bean 生命周期 8 | 完成了 [@ComponentScan](src/com/mafei/spring/anno/ComponentScan.java) 组件扫描、Bean 生命周期`(创建、依赖注入、初始化、销毁)`, 9 | 包括:Bean后处理器 [BeanPostProcessor](src/com/mafei/spring/interfaces/BeanPostProcessor.java) 的调用、各种 Aware 接口回调。 10 | 11 | 依赖注入使用 @Autowired 从容器中 byName 查找依赖。 12 | 13 | ### 循环依赖 14 | - 使用三级缓存解决「属性注入和 set 方法注入」的循环依赖问题,也解决了涉及注入代理对象的循环依赖问题。 15 | - 使用 @Lazy 注解、[ObjectFactory](src/com/mafei/spring/interfaces/ObjectFactory.java) 解决构造方法注入的循环依赖问题 16 | > 两边相互依赖的 bean 必须至少其中一个是单例 bean,才能解决循环依赖问题。采用构造方法注入,单例、多例都行。 17 | > 18 | > 做了循环引用检测,发现循环引用时抛出异常,而不是无限递归爆栈。 19 | > 20 | > 可能会抛出异常的原因: 21 | > - 使用「属性注入或 set 方法注入」两边相互依赖的 bean 都是多例 bean 22 | > - 使用构造方法注入没加 @Lazy、ObjectFactory 推迟注入 bean 23 | 24 | ### 简化的容器 refresh 流程 25 | 1. 收集 BeanDefinition,根据 @ComponentScan 的包路径扫描加了 @Component 注解的类,放入 beanDefinitionMap 26 | 2. 向容器中注册基本的 Bean 后处理器(BeanPostProcessor)BeanDefinition,并创建 beanDefinitionMap 中所有的 Bean 后处理器,放入容器 singletonObjects 中,添加到 beanPostProcessorList 27 | 3. 初始化所有单例 bean 28 | 29 | 容器类的实现是 [MaFeiApplicationContext](src/com/mafei/spring/MaFeiApplicationContext.java) 30 | 31 | ## AOP 32 | 完成了 5 种通知类型([@Before](src/com/mafei/spring/aop/anno/Before.java)、[@AfterReturning](src/com/mafei/spring/aop/anno/AfterReturning.java)、[@After](src/com/mafei/spring/aop/anno/After.java)、[@AfterThrowing](src/com/mafei/spring/aop/anno/AfterThrowing.java)、[@Around](src/com/mafei/spring/aop/anno/Around.java))的解析,对符合切点的目标对象进行代理增强。 33 | 应用在目标方法上的多个通知会链式调用执行,且实现了通知的调用顺序控制(对 [Advisor](src/com/mafei/spring/aop/advisor/Advisor.java) 切面排序)。 34 | 35 | 切点表达式的解析使用 `((String)(expression)).contains(className)` 进行简单地判断,判断通过表示此切面可以应用在这个 class 上,能对这个 class 中所有方法进行增强。 36 | 37 | AOP 功能的实现在 `com.mafei.spring.aop` 包下,通过 Bean 后处理器 [AnnotationAwareAspectJAutoProxyCreator](src/com/mafei/spring/aop/AnnotationAwareAspectJAutoProxyCreator.java) 对符合切点的目标对象进行代理增强。 38 | 如果发生了循环依赖要在依赖注入阶段提前创建代理,此 Bean 后处理器使用缓存避免了代理对象的重复创建。 39 | 40 | 可以使用 [AopContext](src/com/mafei/spring/aop/proxy/AopContext.java) 获取当前线程正在运行的 AOP 代理对象。 41 | 42 | 参考 Spring 源码实现,大部分类名都和 Spring 中的类名一致。 43 | 对 AOP 中的主要接口做了抽象,方便扩展。简单起见,和 Spring 的接口设计略有不同。 44 | 45 | ## 使用到的设计模式 46 | - 代理(JDK 生成动态代理对象) 47 | - 责任链(通知的链式调用) 48 | - 单例(比较器 [OrderComparator](src/com/mafei/spring/core/OrderComparator.java)) 49 | - 适配器(适配各种销毁方法的调用) 50 | - 工厂(ObjectFactory) 51 | 52 | ## 功能测试 Demo 53 | 在 `com.mafei.test` 包下 -------------------------------------------------------------------------------- /src/com/mafei/spring/BeanDefinition.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring; 2 | 3 | /** 4 | * @author mafei007 5 | * @date 2022/6/29 20:08 6 | */ 7 | public class BeanDefinition { 8 | 9 | private Class type; 10 | private String scope; 11 | 12 | public boolean isSingleton() { 13 | return "singleton".equals(scope); 14 | } 15 | 16 | public Class getType() { 17 | return type; 18 | } 19 | 20 | public void setType(Class type) { 21 | this.type = type; 22 | } 23 | 24 | public String getScope() { 25 | return scope; 26 | } 27 | 28 | public void setScope(String scope) { 29 | this.scope = scope; 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return "BeanDefinition{" + 35 | "type=" + type + 36 | ", scope='" + scope + '\'' + 37 | '}'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/com/mafei/spring/DisposableBeanAdapter.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring; 2 | 3 | import com.mafei.spring.interfaces.DisposableBean; 4 | 5 | /** 6 | * 适配器,适配以执行各种形式的销毁方法 7 | * 8 | * @author mafei007 9 | * @date 2022/7/29 19:10 10 | */ 11 | public class DisposableBeanAdapter implements DisposableBean { 12 | 13 | private Object bean; 14 | private String beanName; 15 | private BeanDefinition beanDefinition; 16 | 17 | public DisposableBeanAdapter(Object bean, String beanName, BeanDefinition beanDefinition) { 18 | this.bean = bean; 19 | this.beanName = beanName; 20 | this.beanDefinition = beanDefinition; 21 | } 22 | 23 | public static boolean hasDestroyMethod(Object bean, BeanDefinition beanDefinition) { 24 | if (bean instanceof DisposableBean || bean instanceof AutoCloseable) { 25 | return true; 26 | } 27 | return false; 28 | } 29 | 30 | @Override 31 | public void destroy() { 32 | try { 33 | if (bean instanceof DisposableBean) { 34 | ((DisposableBean) bean).destroy(); 35 | } else if (bean instanceof AutoCloseable) { 36 | ((AutoCloseable) bean).close(); 37 | } 38 | } catch (Exception e) { 39 | System.out.println("Invocation of destroy method failed on bean with name '" + this.beanName + "'"); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/mafei/spring/MaFeiApplicationContext.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring; 2 | 3 | import com.mafei.spring.anno.*; 4 | import com.mafei.spring.aop.AnnotationAwareAspectJAutoProxyCreator; 5 | import com.mafei.spring.aop.proxy.LazyInjectTargetSource; 6 | import com.mafei.spring.aop.proxy.ProxyFactory; 7 | import com.mafei.spring.interfaces.*; 8 | 9 | import java.beans.Introspector; 10 | import java.io.File; 11 | import java.lang.reflect.*; 12 | import java.net.URL; 13 | import java.util.*; 14 | import java.util.concurrent.ConcurrentHashMap; 15 | import java.util.function.Function; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | * 容器启动 20 | * BeanDefinition 扫描 21 | * Bean的生命周期 22 | * 单例与多例Bean 23 | * 依赖注入 24 | * AOP 25 | * Aware回调 26 | * 初始化 27 | * BeanPostProcessor 28 | * 29 | * @author mafei007 30 | * @date 2022/6/29 19:28 31 | */ 32 | public class MaFeiApplicationContext { 33 | 34 | private final Class configClass; 35 | 36 | /** 37 | * beanName -> BeanDefinition 38 | */ 39 | private final Map beanDefinitionMap = new ConcurrentHashMap<>(); 40 | 41 | /** 42 | * Cache of singleton factories: bean name to ObjectFactory. 43 | */ 44 | private final Map> singletonFactories = new HashMap<>(16); 45 | 46 | /** 47 | * Cache of early singleton objects: bean name to bean instance. 48 | */ 49 | private final Map earlySingletonObjects = new ConcurrentHashMap<>(16); 50 | 51 | /** 52 | * 单例池: beanName -> beanObj 53 | */ 54 | private final Map singletonObjects = new ConcurrentHashMap<>(256); 55 | 56 | /** 57 | * Disposable bean instances: bean name to disposable instance. 58 | */ 59 | private final Map disposableBeans = new LinkedHashMap<>(); 60 | 61 | /** 62 | * Names of beans that are currently in creation. 63 | */ 64 | private final Set singletonsCurrentlyInCreation = 65 | Collections.newSetFromMap(new ConcurrentHashMap<>(16)); 66 | 67 | /** 68 | * Names of Prototype beans that are currently in creation. 69 | */ 70 | private final ThreadLocal prototypesCurrentlyInCreation = new ThreadLocal<>(); 71 | 72 | private final List beanPostProcessorList = new ArrayList<>(); 73 | 74 | public MaFeiApplicationContext(Class configClass) { 75 | this.configClass = configClass; 76 | 77 | scanBeanDefinition(configClass); 78 | 79 | registerBeanPostProcessors(); 80 | 81 | preInstantiateSingletons(); 82 | } 83 | 84 | /** 85 | * 扫描 -> 得到一系列 BeanDefinition,放入 beanDefinitionMap 86 | * @param configClass 87 | */ 88 | private void scanBeanDefinition(Class configClass) { 89 | if (configClass.isAnnotationPresent(ComponentScan.class)) { 90 | ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class); 91 | // 扫描路径 com.mafei.test 92 | String path = componentScanAnnotation.value(); 93 | // 扫描路径 com/mafei/test 94 | path = path.replace(".", "/"); 95 | 96 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 97 | // 取得绝对路径: /Users/mafei007/AppProjects/IdeaProjects/spring_study/out/production/simple_impl/com/mafei/test 98 | URL resource = classLoader.getResource(path); 99 | File file = new File(resource.getFile()); 100 | 101 | // 遍历目录下的所有文件,都是 componentScan 需要扫描的,这里只遍历了一层目录 102 | if (file.isDirectory()) { 103 | for (File f : file.listFiles()) { 104 | String fileName = f.getAbsolutePath(); 105 | System.out.println(fileName); 106 | 107 | if (fileName.endsWith(".class")) { 108 | // 提取出 class 对象,需要类的全限定名 109 | // com/mafei/test/Usertest 110 | String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class")); 111 | // com.mafei.test.Usertest 112 | className = className.replace(File.separator, "."); 113 | System.out.println(className); 114 | try { 115 | Class cls = classLoader.loadClass(className); 116 | // 当前 class 是个 Bean 对象 117 | if (cls.isAnnotationPresent(Component.class)) { 118 | Component componentAnno = cls.getAnnotation(Component.class); 119 | String beanName = componentAnno.value(); 120 | 121 | // 生成默认的 beanName 122 | if ("".equals(beanName)) { 123 | beanName = Introspector.decapitalize(cls.getSimpleName()); 124 | } 125 | 126 | // 生成 BeanDefinition,解析 单例bean or 多例bean 127 | BeanDefinition beanDefinition = new BeanDefinition(); 128 | beanDefinition.setType(cls); 129 | if (cls.isAnnotationPresent(Scope.class)) { 130 | Scope scopeAnnotation = cls.getAnnotation(Scope.class); 131 | beanDefinition.setScope(scopeAnnotation.value()); 132 | } else { 133 | beanDefinition.setScope("singleton"); 134 | } 135 | beanDefinitionMap.put(beanName, beanDefinition); 136 | } 137 | } catch (Throwable e) { 138 | throw new RuntimeException(e); 139 | } 140 | } 141 | } 142 | } 143 | } 144 | System.out.println("<<<<<<<<<<<<<<<<<<<<<<"); 145 | } 146 | 147 | /** 148 | * 创建所有 Bean 后处理器,放入 singletonObjects 容器中,并注册到 beanPostProcessorList 149 | *

150 | * 在后续的 preInstantiateSingletons() 初始化单例中,会先从容器中获取,获取不到再创建 151 | * Bean 后处理器属于单例,提前创建好了并放入容器,所以 Bean 后处理器并不会重复创建 152 | */ 153 | private void registerBeanPostProcessors() { 154 | registerCommonBeanPostProcessor(); 155 | /* 156 | 1. 从 beanDefinitionMap 中找出所有的 BeanPostProcessor 157 | 2. 创建 BeanPostProcessor 放入容器 158 | 3. 将创建的 BeanPostProcessor 注册到 beanPostProcessorList 159 | 160 | 这里的写法:先注册的 BeanPostProcessor 会对后创建的 BeanPostProcessor 进行拦截处理, 161 | BeanPostProcessor 的创建走 bean 的生命周期流程 162 | */ 163 | this.beanDefinitionMap.entrySet() 164 | .stream() 165 | .filter((entry) -> BeanPostProcessor.class.isAssignableFrom(entry.getValue().getType())) 166 | .forEach((entry) -> { 167 | BeanPostProcessor beanPostProcessor = (BeanPostProcessor) getBean(entry.getKey()); 168 | this.beanPostProcessorList.add(beanPostProcessor); 169 | }); 170 | } 171 | 172 | /** 173 | * 注册常用的 Bean 后处理器到 beanDefinitionMap 中 174 | */ 175 | private void registerCommonBeanPostProcessor() { 176 | BeanDefinition beanDefinition = new BeanDefinition(); 177 | beanDefinition.setType(AnnotationAwareAspectJAutoProxyCreator.class); 178 | beanDefinition.setScope("singleton"); 179 | beanDefinitionMap.put("internalAutoProxyCreator", beanDefinition); 180 | } 181 | 182 | private void preInstantiateSingletons() { 183 | // 将扫描到的单例 bean 创建出来放到单例池中 184 | beanDefinitionMap.forEach((beanName, beanDefinition) -> { 185 | if (beanDefinition.isSingleton()) { 186 | getBean(beanName); 187 | } 188 | }); 189 | } 190 | 191 | /** 192 | * 创建 bean 193 | * createBean 方法就是在模拟 bean 的声明周期 194 | * 创建、依赖注入、初始化 195 | * 196 | * @param beanName 197 | * @param beanDefinition 198 | * @return 199 | */ 200 | private Object createBean(String beanName, BeanDefinition beanDefinition) { 201 | beforeCreation(beanName, beanDefinition); 202 | try { 203 | // 创建对象 204 | Object bean = createBeanInstance(beanName, beanDefinition); 205 | 206 | // 如果当前创建的是单例对象,依赖注入前将工厂对象 fa 存入三级缓存 singletonFactories 中 207 | if (beanDefinition.isSingleton()) { 208 | System.out.println("🐶🐶🐶🐶 createBean:Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); 209 | this.singletonFactories.put(beanName, new ObjectFactory() { 210 | @Override 211 | public Object getObject() throws RuntimeException { 212 | Object exposedObject = bean; 213 | for (BeanPostProcessor beanPostProcessor : MaFeiApplicationContext.this.beanPostProcessorList) { 214 | if (beanPostProcessor instanceof SmartInstantiationAwareBeanPostProcessor) { 215 | exposedObject = ((SmartInstantiationAwareBeanPostProcessor) beanPostProcessor).getEarlyBeanReference(exposedObject, beanName); 216 | } 217 | } 218 | return exposedObject; 219 | } 220 | }); 221 | this.earlySingletonObjects.remove(beanName); 222 | } 223 | 224 | Object exposedObject = bean; 225 | populateBean(beanName, beanDefinition, bean); 226 | exposedObject = initializeBean(beanName, beanDefinition, exposedObject); 227 | 228 | // 去二级缓存 earlySingletonObjects 中查看有没有当前 bean, 229 | // 如果有,说明发生了循环依赖,返回缓存中的 a 对象(可能是代理对象也可能是原始对象,主要看有没有切点匹配到 bean)。 230 | if (beanDefinition.isSingleton()) { 231 | Object earlySingletonReference = getSingleton(beanName, false); 232 | if (earlySingletonReference != null) { 233 | exposedObject = earlySingletonReference; 234 | } 235 | } 236 | 237 | // 注册 disposable bean,注意注册的是原始对象,而不是代理对象 238 | registerDisposableBeanIfNecessary(beanName, bean, beanDefinition); 239 | 240 | return exposedObject; 241 | } catch (Throwable e) { 242 | throw new RuntimeException(e); 243 | } finally { 244 | afterCreation(beanName, beanDefinition); 245 | } 246 | } 247 | 248 | private void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition) { 249 | if (beanDefinition.isSingleton() && DisposableBeanAdapter.hasDestroyMethod(bean, beanDefinition)) { 250 | this.disposableBeans.put(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition)); 251 | } 252 | } 253 | 254 | private void afterCreation(String beanName, BeanDefinition beanDefinition) { 255 | if (beanDefinition.isSingleton()) { 256 | afterSingletonCreation(beanName); 257 | } else { 258 | afterPrototypeCreation(beanName); 259 | } 260 | } 261 | 262 | @SuppressWarnings("unchecked") 263 | private void afterPrototypeCreation(String beanName) { 264 | Object curVal = this.prototypesCurrentlyInCreation.get(); 265 | if (curVal instanceof String) { 266 | this.prototypesCurrentlyInCreation.remove(); 267 | } else if (curVal instanceof Set) { 268 | Set beanNameSet = (Set) curVal; 269 | beanNameSet.remove(beanName); 270 | if (beanNameSet.isEmpty()) { 271 | this.prototypesCurrentlyInCreation.remove(); 272 | } 273 | } 274 | } 275 | 276 | private void afterSingletonCreation(String beanName) { 277 | if (!this.singletonsCurrentlyInCreation.contains(beanName)) { 278 | // 可能被别的线程修改了 279 | throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); 280 | } 281 | this.singletonsCurrentlyInCreation.remove(beanName); 282 | } 283 | 284 | private void beforeCreation(String beanName, BeanDefinition beanDefinition) { 285 | if (beanDefinition.isSingleton()) { 286 | beforeSingletonCreation(beanName); 287 | } else { 288 | beforePrototypeCreation(beanName); 289 | } 290 | } 291 | 292 | @SuppressWarnings("unchecked") 293 | private void beforePrototypeCreation(String beanName) { 294 | Object curVal = this.prototypesCurrentlyInCreation.get(); 295 | if (curVal != null && 296 | (curVal.equals(beanName) || (curVal instanceof Set && ((Set) curVal).contains(beanName)))) { 297 | throw new IllegalStateException("Error creating prototype bean with name '" + beanName + "': " 298 | + "Requested bean is currently in creation: Is there an unresolvable circular reference?"); 299 | } 300 | // 加入 ThreadLocal 301 | if (curVal == null) { 302 | this.prototypesCurrentlyInCreation.set(beanName); 303 | } else if (curVal instanceof String) { 304 | Set beanNameSet = new HashSet<>(); 305 | beanNameSet.add((String) curVal); 306 | beanNameSet.add(beanName); 307 | this.prototypesCurrentlyInCreation.set(beanNameSet); 308 | } else { 309 | Set beanNameSet = (Set) curVal; 310 | beanNameSet.add(beanName); 311 | } 312 | } 313 | 314 | private void beforeSingletonCreation(String beanName) { 315 | if (this.singletonsCurrentlyInCreation.contains(beanName)) { 316 | throw new IllegalStateException("Error creating singleton bean with name '" + beanName + "': " 317 | + "Requested bean is currently in creation: Is there an unresolvable circular reference?"); 318 | } 319 | this.singletonsCurrentlyInCreation.add(beanName); 320 | } 321 | 322 | /** 323 | * 初始化阶段,包含:Aware回调、初始化前、初始化、初始化后 324 | * 325 | * @param beanName 326 | * @param beanDefinition 327 | * @param bean 328 | * @return 329 | */ 330 | private Object initializeBean(String beanName, BeanDefinition beanDefinition, Object bean) { 331 | // 0️⃣ 各种 Aware 回调 332 | if (bean instanceof BeanNameAware) { 333 | ((BeanNameAware) (bean)).setBeanName(beanName); 334 | } 335 | if (bean instanceof ApplicationContextAware) { 336 | ((ApplicationContextAware) (bean)).setApplicationContext(this); 337 | } 338 | 339 | // 1️⃣ 初始化前 340 | // TODO BeanPostProcessor 解析 @PostConstruct 执行初始化方法 341 | for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) { 342 | bean = beanPostProcessor.postProcessBeforeInitialization(bean, beanName); 343 | } 344 | 345 | // 2️⃣ 初始化 346 | if (bean instanceof InitializingBean) { 347 | ((InitializingBean) (bean)).afterPropertiesSet(); 348 | } 349 | // TODO 执行 @Bean(initMethod = “myInit”) 指定的初始化方法(将初始化方法记录在 BeanDefinition 中) 350 | 351 | // 3️⃣ 初始化后,由 AnnotationAwareAspectJAutoProxyCreator 创建 aop 代理 352 | for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) { 353 | bean = beanPostProcessor.postProcessAfterInitialization(bean, beanName); 354 | } 355 | // 如果有 aop 的话,这里的 bean 返回的是 aop 后的一个代理对象 356 | return bean; 357 | } 358 | 359 | /** 360 | * 依赖注入阶段,执行 bean 后处理器的 postProcessProperties 方法 361 | * 362 | * @param beanName 363 | * @param beanDefinition 364 | * @param bean 365 | */ 366 | private void populateBean(String beanName, BeanDefinition beanDefinition, Object bean) throws IllegalAccessException, InvocationTargetException { 367 | Class clazz = beanDefinition.getType(); 368 | // 解析方法上的 Autowired 369 | for (Method method : clazz.getMethods()) { 370 | if (method.isAnnotationPresent(Autowired.class)) { 371 | // 编译时加上 -parameters 参数才能反射获取到参数名 372 | // 或者编译时加上 -g 参数,使用 ASM 获取到参数名 373 | String paramName = method.getParameters()[0].getName(); 374 | method.invoke(bean, getBean(paramName)); 375 | } 376 | } 377 | // 解析字段上的 Autowired 378 | for (Field field : clazz.getDeclaredFields()) { 379 | if (field.isAnnotationPresent(Autowired.class)) { 380 | field.setAccessible(true); 381 | // 去Spring 容器中找名为 field.getName() 的 bean,赋值给 bean 382 | field.set(bean, getBean(field.getName())); 383 | } 384 | } 385 | 386 | } 387 | 388 | /* 389 | 先将 beanDefinition 扫描出来再创建实例,而不是边扫描边创建 390 | 是因为在 createBean 时,要进行依赖注入,需要看看有没有提供某个类的依赖 391 | 所以要先扫描后创建 392 | */ 393 | 394 | public Object getBean(String beanName) { 395 | BeanDefinition beanDefinition = beanDefinitionMap.get(beanName); 396 | if (beanDefinition == null) { 397 | throw new NullPointerException(); 398 | } else { 399 | // 单例 400 | if (beanDefinition.isSingleton()) { 401 | Object singletonObject = getSingleton(beanName, true); 402 | // 三处缓存都没有某个 bean,只能 create 了 403 | if (singletonObject == null) { 404 | singletonObject = createBean(beanName, beanDefinition); 405 | this.singletonObjects.put(beanName, singletonObject); 406 | this.earlySingletonObjects.remove(beanName); 407 | this.singletonFactories.remove(beanName); 408 | } 409 | return singletonObject; 410 | } else { // 多例 411 | return createBean(beanName, beanDefinition); 412 | } 413 | } 414 | } 415 | 416 | public T getBean(String beanName, Class requiredType) { 417 | return (T) getBean(beanName); 418 | } 419 | 420 | /** 421 | * 尝试依次从 3 处缓存中取 422 | * 423 | * @param beanName 424 | * @param allowEarlyReference 是否应该创建早期引用。 425 | * bean 初始化后应该检查二级缓存是否提前创建了 bean,此时 allowEarlyReference 为 false,只检查到二级缓存即可 426 | * @return 427 | */ 428 | private Object getSingleton(String beanName, boolean allowEarlyReference) { 429 | // 一级缓存: 单例池 430 | Object singletonObject = this.singletonObjects.get(beanName); 431 | if (singletonObject == null) { 432 | // 二级缓存:提前创建的单例对象池 433 | singletonObject = this.earlySingletonObjects.get(beanName); 434 | if (singletonObject == null && allowEarlyReference) { 435 | // 三级缓存:单例工厂池 436 | ObjectFactory objectFactory = this.singletonFactories.get(beanName); 437 | if (objectFactory != null) { 438 | singletonObject = objectFactory.getObject(); 439 | this.earlySingletonObjects.put(beanName, singletonObject); 440 | this.singletonFactories.remove(beanName); 441 | } 442 | } 443 | } 444 | return singletonObject; 445 | } 446 | 447 | public List> getAllBeanClass() { 448 | return beanDefinitionMap.values() 449 | .stream() 450 | .map((Function>) BeanDefinition::getType) 451 | .collect(Collectors.toList()); 452 | } 453 | 454 | public ArrayList getBeanNames() { 455 | return new ArrayList<>(beanDefinitionMap.keySet()); 456 | /*Enumeration keys = beanDefinitionMap.keys(); 457 | ArrayList ret = new ArrayList<>(); 458 | while (keys.hasMoreElements()) { 459 | String beanName = keys.nextElement(); 460 | ret.add(beanName); 461 | } 462 | return ret;*/ 463 | } 464 | 465 | /** 466 | * 创建 bean 467 | * 编译时加上 -parameters 参数才能反射获取到参数名 468 | * 或者编译时加上 -g 参数,使用 ASM 获取到参数名 469 | * 470 | * @param beanName 471 | * @param beanDefinition 472 | * @return 473 | * @throws Throwable 474 | */ 475 | private Object createBeanInstance(String beanName, BeanDefinition beanDefinition) throws Throwable { 476 | Class clazz = beanDefinition.getType(); 477 | // 优先使用无参构造 478 | Constructor[] constructors = clazz.getConstructors(); 479 | for (Constructor constructor : constructors) { 480 | if (constructor.getParameterCount() == 0) { 481 | return constructor.newInstance(); 482 | } 483 | } 484 | // 没有无参构造,使用有参构造,随机选一个构造器 485 | Constructor constructor = constructors[0]; 486 | Object[] args = new Object[constructor.getParameterCount()]; 487 | Parameter[] parameters = constructor.getParameters(); 488 | for (int i = 0; i < parameters.length; i++) { 489 | Parameter parameter = parameters[i]; 490 | Object arg = null; 491 | if (parameter.getType().equals(ObjectFactory.class)) { // ObjectFactory 参数 492 | arg = buildLazyObjectFactory(parameter.getName()); 493 | } else if (parameter.isAnnotationPresent(Lazy.class)) { // 参数加了 @Lazy,生成代理 494 | arg = buildLazyResolutionProxy(parameter.getName(), parameter.getType()); 495 | } else { // 不是 ObjectFactory 也没加 @Lazy 的,直接从容器中拿 496 | arg = getBean(parameter.getName()); 497 | } 498 | args[i] = arg; 499 | } 500 | return constructor.newInstance(args); 501 | } 502 | 503 | private Object buildLazyObjectFactory(String requestingBeanName) { 504 | return new ObjectFactory() { 505 | @Override 506 | public Object getObject() throws RuntimeException { 507 | return getBean(requestingBeanName); 508 | } 509 | }; 510 | } 511 | 512 | private Object buildLazyResolutionProxy(String requestingBeanName, Class clazz) { 513 | LazyInjectTargetSource targetSource = new LazyInjectTargetSource(this, requestingBeanName); 514 | ProxyFactory proxyFactory = new ProxyFactory(); 515 | proxyFactory.setTargetSource(targetSource); 516 | proxyFactory.setInterfaces(clazz.getInterfaces()); 517 | // 临时的解决方案,JDK 动态代理只能基于接口,要代理的 class 可能本身是个接口,添加进去 518 | if (clazz.isInterface()) { 519 | proxyFactory.addInterface(clazz); 520 | } 521 | System.out.println("🐷🐷🐷🐷 使用有参构造,为 " + requestingBeanName + " 参数创建代理对象"); 522 | return proxyFactory.getProxy(); 523 | } 524 | 525 | public void close() { 526 | destroySingletons(); 527 | } 528 | 529 | private void destroySingletons() { 530 | synchronized (this.disposableBeans) { 531 | Set> entrySet = this.disposableBeans.entrySet(); 532 | Iterator> it = entrySet.iterator(); 533 | while (it.hasNext()) { 534 | Map.Entry entry = it.next(); 535 | String beanName = entry.getKey(); 536 | DisposableBean bean = (DisposableBean) entry.getValue(); 537 | try { 538 | bean.destroy(); 539 | } catch (Exception e) { 540 | System.out.println("Destruction of bean with name '" + beanName + "' threw an exception:" + e); 541 | } 542 | it.remove(); 543 | } 544 | } 545 | // Clear all cached singleton instances in this registry. 546 | this.singletonObjects.clear(); 547 | this.earlySingletonObjects.clear(); 548 | this.singletonFactories.clear(); 549 | } 550 | 551 | /** 552 | * 对外提供销毁 bean 的方法 553 | * @param beanName 554 | * @param bean 555 | */ 556 | public void destroyBean(String beanName, Object bean) { 557 | // beanDefinition 未处理 558 | new DisposableBeanAdapter(bean, beanName, null).destroy(); 559 | } 560 | 561 | public void destroyBean(Object bean) { 562 | new DisposableBeanAdapter(bean, bean.getClass().getName(), null).destroy(); 563 | } 564 | 565 | } 566 | -------------------------------------------------------------------------------- /src/com/mafei/spring/anno/Autowired.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.anno; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author mafei007 10 | * @date 2022/6/29 20:07 11 | */ 12 | @Target({ElementType.FIELD, ElementType.METHOD}) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface Autowired { 15 | } 16 | -------------------------------------------------------------------------------- /src/com/mafei/spring/anno/Component.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.anno; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author mafei007 10 | * @date 2022/6/29 19:30 11 | */ 12 | @Target(ElementType.TYPE) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface Component { 15 | String value() default ""; 16 | } 17 | -------------------------------------------------------------------------------- /src/com/mafei/spring/anno/ComponentScan.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.anno; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author mafei007 10 | * @date 2022/6/29 19:30 11 | */ 12 | @Target(ElementType.TYPE) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface ComponentScan { 15 | String value() default ""; 16 | } 17 | -------------------------------------------------------------------------------- /src/com/mafei/spring/anno/Lazy.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.anno; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * 加在构造方法参数上面, 10 | * 对加了 @Lazy 注解的依赖生成代理对象,推迟 bean 的获取, 11 | * 解决构造方法的循环依赖问题 12 | * 13 | * @author mafei007 14 | * @date 2022/7/24 19:20 15 | */ 16 | @Target(ElementType.PARAMETER) 17 | @Retention(RetentionPolicy.RUNTIME) 18 | public @interface Lazy { 19 | } 20 | -------------------------------------------------------------------------------- /src/com/mafei/spring/anno/Scope.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.anno; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author mafei007 10 | * @date 2022/6/29 20:07 11 | */ 12 | @Target(ElementType.TYPE) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface Scope { 15 | String value() default ""; 16 | } 17 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/AnnotationAwareAspectJAutoProxyCreator.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop; 2 | 3 | import com.mafei.spring.MaFeiApplicationContext; 4 | import com.mafei.spring.aop.advisor.Advice; 5 | import com.mafei.spring.aop.advisor.Advisor; 6 | import com.mafei.spring.aop.advisor.MethodMatcher; 7 | import com.mafei.spring.aop.advisor.Pointcut; 8 | import com.mafei.spring.aop.proxy.ProxyFactory; 9 | import com.mafei.spring.aop.proxy.SingletonTargetSource; 10 | import com.mafei.spring.core.OrderComparator; 11 | import com.mafei.spring.interfaces.ApplicationContextAware; 12 | import com.mafei.spring.interfaces.SmartInstantiationAwareBeanPostProcessor; 13 | 14 | import java.lang.reflect.Method; 15 | import java.util.ArrayList; 16 | import java.util.HashSet; 17 | import java.util.List; 18 | import java.util.Set; 19 | 20 | /** 21 | * bean 后处理器,对符合条件的 bean 进行 aop 代理增强,创建代理对象 22 | * 23 | * @author mafei007 24 | * @date 2022/7/7 20:23 25 | */ 26 | public class AnnotationAwareAspectJAutoProxyCreator implements SmartInstantiationAwareBeanPostProcessor, ApplicationContextAware { 27 | 28 | private MaFeiApplicationContext applicationContext; 29 | 30 | private final AspectJAdvisorFactory advisorFactory = new DefaultAspectJAdvisorFactory(); 31 | 32 | private List cachedAdvisors; 33 | 34 | /** 35 | * 记录哪些 bean 尝试过提前创建代理,无论这个 bean 是否创建了代理增强,都记录下来, 36 | * 等到初始化阶段进行创建代理时,检查缓存,避免重复创建代理。 37 | * 存储的值就是 beanName 38 | */ 39 | private final Set earlyProxyReferences = new HashSet<>(); 40 | 41 | @Override 42 | public Object getEarlyBeanReference(Object bean, String beanName) throws RuntimeException { 43 | this.earlyProxyReferences.add(beanName); 44 | return wrapIfNecessary(bean, beanName); 45 | } 46 | 47 | @Override 48 | public Object postProcessBeforeInitialization(Object bean, String beanName) { 49 | return SmartInstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); 50 | } 51 | 52 | @Override 53 | public Object postProcessAfterInitialization(Object bean, String beanName) { 54 | if (bean != null) { 55 | // earlyProxyReferences 中不包含当前 beanName,才创建代理 56 | if (!this.earlyProxyReferences.contains(beanName)) { 57 | return wrapIfNecessary(bean, beanName); 58 | } else { 59 | // earlyProxyReferences 中包含当前 beanName,不再重复进行代理创建,直接返回 60 | this.earlyProxyReferences.remove(beanName); 61 | } 62 | } 63 | return bean; 64 | } 65 | 66 | 67 | private Object wrapIfNecessary(Object bean, String beanName) { 68 | if (isInfrastructureClass(bean.getClass())) { 69 | return bean; 70 | } 71 | List advisorList = findEligibleAdvisors(bean.getClass(), beanName); 72 | if (!advisorList.isEmpty()) { 73 | Object proxy = createProxy(bean.getClass(), bean, beanName, advisorList); 74 | return proxy; 75 | } 76 | System.out.println("………………………………………………Did not to auto-proxy user class [" + bean.getClass().getName() + "], beanName[" + beanName + "]"); 77 | return bean; 78 | } 79 | 80 | protected boolean isInfrastructureClass(Class beanClass) { 81 | boolean retVal = Advice.class.isAssignableFrom(beanClass) || 82 | Pointcut.class.isAssignableFrom(beanClass) || 83 | Advisor.class.isAssignableFrom(beanClass) || 84 | this.advisorFactory.isAspect(beanClass); 85 | if (retVal) { 86 | // logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]"); 87 | System.out.println("………………………………………………Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]"); 88 | } 89 | return retVal; 90 | } 91 | 92 | private Object createProxy(Class targetClass, Object target, String beanName, List advisorList) { 93 | ProxyFactory proxyFactory = new ProxyFactory(); 94 | proxyFactory.setTargetSource(new SingletonTargetSource(target)); 95 | proxyFactory.addAdvisors(advisorList); 96 | proxyFactory.setInterfaces(targetClass.getInterfaces()); 97 | 98 | System.out.println("给 " + beanName + " 创建代理,有 " + advisorList.size() + " 个切面。"); 99 | return proxyFactory.getProxy(); 100 | } 101 | 102 | private List findEligibleAdvisors(Class beanClass, String beanName) { 103 | List candidateAdvisors = findCandidateAdvisors(); 104 | List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); 105 | // 如果最终的 Advisor 列表不为空,再在开头位置添加一个 ExposeInvocationInterceptor 106 | // extendAdvisors(eligibleAdvisors); 107 | if (!eligibleAdvisors.isEmpty()) { 108 | OrderComparator.sort(eligibleAdvisors); 109 | } 110 | return eligibleAdvisors; 111 | } 112 | 113 | private List findAdvisorsThatCanApply(List candidateAdvisors, Class beanClass, String beanName) { 114 | if (candidateAdvisors.isEmpty()) { 115 | return candidateAdvisors; 116 | } 117 | List eligibleAdvisors = new ArrayList<>(candidateAdvisors.size()); 118 | Method[] methods = beanClass.getDeclaredMethods(); 119 | 120 | // 遍历 bean 目标类型的所有方法,包括继承来的接口方法等 121 | // 继承的方法没写 122 | 123 | // 双重 for 循环 124 | for (Advisor advisor : candidateAdvisors) { 125 | MethodMatcher methodMatcher = advisor.getPointcut().getMethodMatcher(); 126 | for (Method method : methods) { 127 | if (methodMatcher.matches(method, beanClass)) { 128 | eligibleAdvisors.add(advisor); 129 | break; 130 | } 131 | } 132 | } 133 | return eligibleAdvisors; 134 | } 135 | 136 | private List findCandidateAdvisors() { 137 | List advisors = findCandidateAdvisorsInBeanFactory(); 138 | advisors.addAll(findCandidateAdvisorsInAspect()); 139 | return advisors; 140 | } 141 | 142 | /** 143 | * 遍历 beanFactory 中所有 bean,找到被 @Aspect 注解标注的 bean,再去 @Aspect 类中封装 Advisor 144 | * 145 | * @return 146 | */ 147 | private List findCandidateAdvisorsInAspect() { 148 | if (this.cachedAdvisors != null) { 149 | return this.cachedAdvisors; 150 | } 151 | List> allClass = applicationContext.getAllBeanClass(); 152 | List advisors = new ArrayList<>(); 153 | 154 | for (Class cls : allClass) { 155 | if (this.advisorFactory.isAspect(cls)) { 156 | List classAdvisors = this.advisorFactory.getAdvisors(cls); 157 | advisors.addAll(classAdvisors); 158 | } 159 | } 160 | this.cachedAdvisors = advisors; 161 | return this.cachedAdvisors; 162 | } 163 | 164 | /** 165 | * 去容器中拿所有低级 Advisor 166 | * 167 | * @return 168 | */ 169 | private List findCandidateAdvisorsInBeanFactory() { 170 | return new ArrayList<>(); 171 | } 172 | 173 | @Override 174 | public void setApplicationContext(MaFeiApplicationContext applicationContext) { 175 | this.applicationContext = applicationContext; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/AspectInstanceFactory.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop; 2 | 3 | /** 4 | * 提供调用切面方法的类 5 | * @author mafei007 6 | * @date 2022/7/7 21:47 7 | */ 8 | public interface AspectInstanceFactory { 9 | /** 10 | * Create an instance of this factory's aspect. 11 | * @return the aspect instance (never {@code null}) 12 | */ 13 | Object getAspectInstance(); 14 | } 15 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/AspectJAdvisorFactory.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop; 2 | 3 | import com.mafei.spring.aop.advisor.Advisor; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 解析 @Aspect 切面类中的所有切面 9 | * @author mafei007 10 | * @date 2022/7/7 21:32 11 | */ 12 | public interface AspectJAdvisorFactory { 13 | 14 | /** 15 | * 是否是切面类 @Aspect 16 | * @param clazz 17 | * @return 18 | */ 19 | boolean isAspect(Class clazz); 20 | 21 | /** 22 | * 解析 @Aspect 切面类中的所有切面 23 | * @param clazz 24 | * @return 25 | */ 26 | List getAdvisors(Class clazz); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/DefaultAspectJAdvisorFactory.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop; 2 | 3 | import com.mafei.spring.aop.advisor.Advisor; 4 | import com.mafei.spring.aop.advisor.AspectJExpressionPointcut; 5 | import com.mafei.spring.aop.advisor.DefaultPointcutAdvisor; 6 | import com.mafei.spring.aop.advisor.joinpoint.ProceedingJoinPoint; 7 | import com.mafei.spring.aop.anno.*; 8 | 9 | import java.lang.reflect.Method; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * @author mafei007 15 | * @date 2022/7/7 21:38 16 | */ 17 | public class DefaultAspectJAdvisorFactory implements AspectJAdvisorFactory { 18 | @Override 19 | public boolean isAspect(Class clazz) { 20 | return clazz.isAnnotationPresent(Aspect.class); 21 | } 22 | 23 | @Override 24 | public List getAdvisors(Class clazz) { 25 | PrototypeAspectInstanceFactory aspectInstanceFactory = new PrototypeAspectInstanceFactory(clazz); 26 | // 高级切面转低级切面类 27 | List list = new ArrayList<>(); 28 | 29 | for (Method method : clazz.getDeclaredMethods()) { 30 | if (method.isAnnotationPresent(Before.class)) { 31 | // 切点 pointcut 32 | String expression = method.getAnnotation(Before.class).value(); 33 | AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); 34 | pointcut.setExpression(expression); 35 | // 通知 (最终都是环绕通知) 36 | BeforeAdvice advice = new BeforeAdvice(method, aspectInstanceFactory); 37 | // 切面 38 | Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice); 39 | list.add(advisor); 40 | } else if (method.isAnnotationPresent(After.class)) { 41 | // 切点 pointcut 42 | String expression = method.getAnnotation(After.class).value(); 43 | AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); 44 | pointcut.setExpression(expression); 45 | // 通知 (最终都是环绕通知) 46 | AfterAdvice advice = new AfterAdvice(method, aspectInstanceFactory); 47 | // 切面 48 | Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice); 49 | list.add(advisor); 50 | } else if (method.isAnnotationPresent(AfterReturning.class)) { 51 | // 切点 pointcut 52 | String expression = method.getAnnotation(AfterReturning.class).value(); 53 | AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); 54 | pointcut.setExpression(expression); 55 | // 通知 (最终都是环绕通知) 56 | AfterReturningAdvice advice = new AfterReturningAdvice(method, aspectInstanceFactory); 57 | // 切面 58 | Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice); 59 | list.add(advisor); 60 | } else if (method.isAnnotationPresent(AfterThrowing.class)) { 61 | // 切点 pointcut 62 | AfterThrowing afterThrowing = method.getAnnotation(AfterThrowing.class); 63 | String expression = afterThrowing.value(); 64 | AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); 65 | pointcut.setExpression(expression); 66 | // 通知 (最终都是环绕通知) 67 | AfterThrowingAdvice advice = new AfterThrowingAdvice(method, aspectInstanceFactory); 68 | advice.setThrowingName(afterThrowing.throwing()); 69 | // 切面 70 | Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice); 71 | list.add(advisor); 72 | } else if (method.isAnnotationPresent(Around.class)) { 73 | if (method.getParameterCount() == 0) { 74 | throw new IllegalStateException("环绕通知的参数中缺少 ProceedingJoinPoint"); 75 | } 76 | if (!method.getParameterTypes()[0].equals(ProceedingJoinPoint.class)) { 77 | throw new IllegalStateException("环绕通知的参数中第一个位置必须是 ProceedingJoinPoint"); 78 | } 79 | // 切点 pointcut 80 | Around around = method.getAnnotation(Around.class); 81 | String expression = around.value(); 82 | AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); 83 | pointcut.setExpression(expression); 84 | // 通知 (最终都是环绕通知) 85 | AroundAdvice advice = new AroundAdvice(method, aspectInstanceFactory); 86 | // 切面 87 | Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice); 88 | list.add(advisor); 89 | } 90 | } 91 | return list; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/PrototypeAspectInstanceFactory.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop; 2 | 3 | /** 4 | * 提供调用切面方法的类 5 | * 每次返回新的切面对象 6 | * @author mafei007 7 | * @date 2022/7/8 00:04 8 | */ 9 | public class PrototypeAspectInstanceFactory implements AspectInstanceFactory{ 10 | 11 | private Class clazz; 12 | 13 | public PrototypeAspectInstanceFactory(Class clazz) { 14 | this.clazz = clazz; 15 | } 16 | 17 | @Override 18 | public Object getAspectInstance() { 19 | try { 20 | return clazz.newInstance(); 21 | } catch (InstantiationException e) { 22 | e.printStackTrace(); 23 | } catch (IllegalAccessException e) { 24 | e.printStackTrace(); 25 | } 26 | return null; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/SingletonAspectInstanceFactory.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop; 2 | 3 | /** 4 | * 提供调用切面方法的类 5 | * 单例工厂,每次返回相同的对象,计划从容器中拿 6 | * @author mafei007 7 | * @date 2022/7/7 21:48 8 | */ 9 | public class SingletonAspectInstanceFactory implements AspectInstanceFactory{ 10 | 11 | private Object aspectInstance; 12 | 13 | public SingletonAspectInstanceFactory(Object aspectInstance) { 14 | this.aspectInstance = aspectInstance; 15 | } 16 | 17 | @Override 18 | public Object getAspectInstance() { 19 | return this.aspectInstance; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/Advice.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor; 2 | 3 | import com.mafei.spring.core.Ordered; 4 | 5 | /** 6 | * 通知 7 | * Spring 中此接口并没有实现 Ordered,而是使用别的方法进行排序 8 | * 9 | * @author mafei007 10 | * @date 2022/7/7 20:59 11 | */ 12 | public interface Advice extends Ordered { 13 | } 14 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/Advisor.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor; 2 | 3 | import com.mafei.spring.core.Ordered; 4 | 5 | /** 6 | * 切面 7 | * Spring 中此接口并没有实现 Ordered,而是使用别的方法进行排序 8 | * 9 | * @author mafei007 10 | * @date 2022/7/7 20:58 11 | */ 12 | public interface Advisor extends Ordered { 13 | 14 | /** 15 | * 此方法应该再封装一个接口:PointcutAdvisor,放在这个接口里,这里直接放在 Advisor 接口 里了 16 | * @return 17 | */ 18 | Pointcut getPointcut(); 19 | 20 | Advice getAdvice(); 21 | } 22 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/AspectJExpressionPointcut.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor; 2 | 3 | import com.mafei.spring.aop.advisor.MethodMatcher; 4 | import com.mafei.spring.aop.advisor.Pointcut; 5 | 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * 既是 Pointcut,又是 MethodMatcher 10 | * @author mafei007 11 | * @date 2022/7/7 22:14 12 | */ 13 | public class AspectJExpressionPointcut implements Pointcut, MethodMatcher { 14 | 15 | private String expression; 16 | 17 | public void setExpression(String expression) { 18 | this.expression = expression; 19 | } 20 | 21 | @Override 22 | public MethodMatcher getMethodMatcher() { 23 | return this; 24 | } 25 | 26 | @Override 27 | public boolean matches(Method method, Class targetClass) { 28 | if (expression.startsWith("execution")) { 29 | return executionMatches(method, targetClass); 30 | } else if (expression.startsWith("@annotation")) { 31 | return annotationMatches(method, targetClass); 32 | } else { 33 | System.out.println("未知 expression,默认返回 true"); 34 | return true; 35 | } 36 | } 37 | 38 | /** 39 | * 解析这种:"@annotation(org.springframework.transaction.annotation.Transactional)" 40 | * 判断方法上是否有 expression 表达式里的注解就行了 41 | * 42 | * "@annotation(org.springframework.web.bind.annotation.GetMapping)" 43 | * 所有被GetMapping注解修饰的方法会织入advice 44 | * @param method 45 | * @param targetClass 46 | * @return 47 | */ 48 | private boolean annotationMatches(Method method, Class targetClass) { 49 | return true; 50 | } 51 | 52 | private boolean executionMatches(Method method, Class targetClass) { 53 | String simpleName = targetClass.getSimpleName(); 54 | if (expression.contains(simpleName)) { 55 | return true; 56 | } 57 | return false; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/CommonAdvice.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor; 2 | 3 | import com.mafei.spring.aop.AspectInstanceFactory; 4 | import com.mafei.spring.aop.advisor.joinpoint.ProceedingJoinPoint; 5 | import com.mafei.spring.core.Ordered; 6 | 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.lang.reflect.Method; 9 | import java.lang.reflect.Parameter; 10 | 11 | /** 12 | * @author mafei007 13 | * @date 2022/7/7 23:04 14 | */ 15 | public abstract class CommonAdvice implements Advice, Ordered { 16 | 17 | private Method aspectJAdviceMethod; 18 | private AspectInstanceFactory aspectInstanceFactory; 19 | 20 | /** 21 | * 默认拦截所有的异常类型 22 | */ 23 | private Class discoveredThrowingType = Object.class; 24 | 25 | /** 26 | * @AfterThrowing( value = "execution(* foo())", throwing = "java.lang.ClassNotFoundException") 27 | * throwing 的值 28 | */ 29 | private String throwingName; 30 | 31 | public CommonAdvice(Method aspectJAdviceMethod, AspectInstanceFactory aspectInstanceFactory) { 32 | aspectJAdviceMethod.setAccessible(true); 33 | this.aspectJAdviceMethod = aspectJAdviceMethod; 34 | this.aspectInstanceFactory = aspectInstanceFactory; 35 | } 36 | 37 | 38 | /** 39 | * 调用通知方法,完成简单的参数回显解析 40 | * 41 | * @return 42 | */ 43 | protected Object invokeAdviceMethod(ProceedingJoinPoint pjp, Throwable ex) throws Throwable { 44 | // 准备方法参数 45 | int parameterCount = this.aspectJAdviceMethod.getParameterCount(); 46 | Object[] args = new Object[parameterCount]; 47 | 48 | // 存在异常,@AfterThrowing 通知的调用 49 | if (ex != null) { 50 | // 设置了 throwingName,但没有通知方法中没有参数,报错 51 | // 例:对应默认的 @AfterThrowing ,注解中不设置 throwing 52 | if (parameterCount == 0) { 53 | if (this.throwingName != null) { 54 | throw new IllegalStateException("Throwing argument name '" + this.throwingName + 55 | "' was not bound in advice arguments"); 56 | } 57 | } else { 58 | // 通知方法如果有参数的话,第一个参数必须是异常类型 59 | args[0] = ex; 60 | } 61 | } 62 | 63 | // 存在 ProceedingJoinPoint, @Around 通知的调用 64 | if (pjp != null) { 65 | if (parameterCount == 0) { 66 | throw new IllegalStateException("环绕通知的参数中缺少 ProceedingJoinPoint"); 67 | } else { 68 | args[0] = pjp; 69 | } 70 | } 71 | return invokeAdviceMethod(args); 72 | } 73 | 74 | /** 75 | * AfterThrowing 异常回显 76 | * 环绕通知会用到通知方法的返回值,其他通知用不到 77 | * 78 | * @param args 79 | * @return 80 | */ 81 | private Object invokeAdviceMethod(Object[] args) throws Throwable { 82 | try { 83 | return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), args); 84 | } catch (IllegalAccessException e) { 85 | throw e; 86 | } catch (InvocationTargetException e) { 87 | throw e.getTargetException(); 88 | } 89 | } 90 | 91 | protected void setThrowingName(String name) { 92 | if (name.equals("ex")) { 93 | this.throwingName = name; 94 | // 下面的方法不行,因为编译后的 class 没有参数名信息,变成 arg0、arg1 这种 95 | /*Parameter[] parameters = this.aspectJAdviceMethod.getParameters(); 96 | for (Parameter parameter : parameters) { 97 | // 找到要拦截的异常类型 98 | if (parameter.getName().equals(this.throwingName)) { 99 | this.discoveredThrowingType = parameter.getType(); 100 | return; 101 | } 102 | }*/ 103 | // 规定如果 @AfterThrowing 的 throwing 参数设置为 ex,那么参数列表第 0 个必须是异常类 104 | Class exClass = null; 105 | try { 106 | exClass = this.aspectJAdviceMethod.getParameterTypes()[0]; 107 | } catch (ArrayIndexOutOfBoundsException e) { 108 | throw new IllegalArgumentException("方法中缺少异常参数。method = " + this.aspectJAdviceMethod); 109 | } 110 | 111 | if (Throwable.class.isAssignableFrom(exClass)) { 112 | this.discoveredThrowingType = exClass; 113 | } else { 114 | throw new IllegalArgumentException("方法中缺少异常参数,找不到要拦截的异常类型。method = " + this.aspectJAdviceMethod); 115 | } 116 | } else if (name.length() > 0) { 117 | this.throwingName = name; 118 | try { 119 | this.discoveredThrowingType = Class.forName(name); 120 | } catch (Throwable ex) { 121 | throw new IllegalArgumentException("Throwing name '" + name + 122 | "' is neither a valid argument name nor the fully-qualified " + 123 | "name of a Java type on the classpath. Root cause: " + ex); 124 | } 125 | } else { 126 | // throwing 没提供,默认拦截索引异常 127 | } 128 | } 129 | 130 | protected Class getDiscoveredThrowingType() { 131 | return this.discoveredThrowingType; 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/DefaultMethodInvocation.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor; 2 | 3 | import com.mafei.spring.aop.util.AopUtils; 4 | 5 | import java.lang.reflect.Method; 6 | import java.util.List; 7 | 8 | /** 9 | * @author mafei007 10 | * @date 2022/7/8 02:05 11 | */ 12 | public class DefaultMethodInvocation implements MethodInvocation { 13 | 14 | private Object target; 15 | private Method method; 16 | private Object[] args; 17 | List methodInterceptorList; 18 | // 调用位置 19 | private int currentInterceptorIndex = -1; 20 | 21 | public DefaultMethodInvocation(Object target, Method method, Object[] args, List methodInterceptorList) { 22 | this.target = target; 23 | this.method = method; 24 | if (args == null) { 25 | this.args = new Object[0]; 26 | } else { 27 | this.args = args; 28 | } 29 | this.methodInterceptorList = methodInterceptorList; 30 | } 31 | 32 | @Override 33 | public Object proceed() throws Throwable { 34 | // 调用目标, 返回并结束递归 35 | if (this.currentInterceptorIndex == this.methodInterceptorList.size() - 1) { 36 | return invokeJoinpoint(); 37 | } 38 | // 逐一调用通知, currentInterceptorIndex + 1 39 | Object methodInterceptor = this.methodInterceptorList.get(++currentInterceptorIndex); 40 | return ((MethodInterceptor) methodInterceptor).invoke(this); 41 | } 42 | 43 | protected Object invokeJoinpoint() throws Throwable { 44 | return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.args); 45 | } 46 | 47 | @Override 48 | public Object[] getArguments() { 49 | return this.args; 50 | } 51 | 52 | @Override 53 | public void setArguments(Object[] args) { 54 | this.args = args; 55 | } 56 | 57 | @Override 58 | public Method getMethod() { 59 | return this.method; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/DefaultPointcutAdvisor.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor; 2 | 3 | import com.mafei.spring.core.Ordered; 4 | 5 | /** 6 | * @author mafei007 7 | * @date 2022/7/8 00:12 8 | */ 9 | public class DefaultPointcutAdvisor implements Advisor { 10 | 11 | private Pointcut pointcut; 12 | private Advice advice; 13 | 14 | public DefaultPointcutAdvisor(Pointcut pointcut, Advice advice) { 15 | this.pointcut = pointcut; 16 | this.advice = advice; 17 | } 18 | 19 | @Override 20 | public Pointcut getPointcut() { 21 | return pointcut; 22 | } 23 | 24 | @Override 25 | public Advice getAdvice() { 26 | return advice; 27 | } 28 | 29 | @Override 30 | public int getOrder() { 31 | return this.advice.getOrder(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/Interceptor.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor; 2 | 3 | /** 4 | * @author mafei007 5 | * @date 2022/7/8 01:44 6 | */ 7 | public interface Interceptor extends Advice{ 8 | } 9 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/Joinpoint.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor; 2 | 3 | /** 4 | * 连接点,是程序执行的一个点。例如,一个方法的执行或者一个异常的处理。 5 | * 在 Spring AOP 中,一个连接点总是代表一个方法执行。 6 | * @author mafei007 7 | * @date 2022/7/7 22:47 8 | */ 9 | public interface Joinpoint { 10 | 11 | Object proceed() throws Throwable; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/MethodInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor; 2 | 3 | /** 4 | * 环绕通知 5 | * @author mafei007 6 | * @date 2022/7/7 22:45 7 | */ 8 | public interface MethodInterceptor extends Interceptor { 9 | 10 | Object invoke(MethodInvocation invocation) throws Throwable; 11 | } 12 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/MethodInvocation.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * 调用链 7 | * 8 | * @author mafei007 9 | * @date 2022/7/7 22:48 10 | */ 11 | public interface MethodInvocation extends Joinpoint { 12 | 13 | /** 14 | * 获得执行链中目标方法的实参 15 | * @return 16 | */ 17 | Object[] getArguments(); 18 | 19 | /** 20 | * 修改执行链中目标方法的实参 21 | * ProxyMethodInvocation 中的功能,这里直接放在 MethodInvocation 中了,允许修改实参 22 | */ 23 | void setArguments(Object[] args); 24 | 25 | /** 26 | * 获得执行链中的目标方法 27 | * @return 28 | */ 29 | Method getMethod(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/MethodMatcher.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * Part of a Pointcut: Checks whether the target method is eligible for advice. 7 | * 8 | * @author mafei007 9 | * @date 2022/7/7 22:08 10 | */ 11 | public interface MethodMatcher { 12 | 13 | /** 14 | * Perform static checking whether the given method matches. 15 | * 16 | * @param method the candidate method 17 | * @param targetClass the target class 18 | * @return whether or not this method matches statically 19 | */ 20 | boolean matches(Method method, Class targetClass); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/Pointcut.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor; 2 | 3 | /** 4 | * Core Spring pointcut abstraction. 5 | * 切点使用一个 MethodMatcher 对象来判断某个方法是否有资格用于切面 6 | * 7 | * @author mafei007 8 | * @date 2022/7/7 22:11 9 | */ 10 | public interface Pointcut { 11 | 12 | /** 13 | * Return the MethodMatcher for this pointcut. 14 | * @return the MethodMatcher (never {@code null}) 15 | */ 16 | MethodMatcher getMethodMatcher(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/joinpoint/JoinPoint.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor.joinpoint; 2 | 3 | /** 4 | * 使用在通知方法的参数上,用于获取各种信息 5 | *

6 | * 注意对比 com.mafei.spring.aop.advisor.Joinpoint,这个是切入点方法执行的顶级接口 7 | * 8 | * @author mafei007 9 | * @date 2022/7/8 22:44 10 | */ 11 | public interface JoinPoint { 12 | 13 | /** 14 | * 获取执行链中目标方法的实参 15 | * @return 16 | */ 17 | Object[] getArgs(); 18 | 19 | /** 20 | * 获取执行链中目标方法的方法名 21 | * @return 22 | */ 23 | String getMethodName(); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/joinpoint/MethodInvocationProceedingJoinPoint.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor.joinpoint; 2 | 3 | import com.mafei.spring.aop.advisor.MethodInvocation; 4 | 5 | /** 6 | * @author mafei007 7 | * @date 2022/7/8 22:58 8 | */ 9 | public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint { 10 | 11 | private final MethodInvocation methodInvocation; 12 | 13 | public MethodInvocationProceedingJoinPoint(MethodInvocation mi) { 14 | this.methodInvocation = mi; 15 | } 16 | 17 | @Override 18 | public Object proceed() throws Throwable { 19 | return this.methodInvocation.proceed(); 20 | } 21 | 22 | @Override 23 | public Object proceed(Object[] args) throws Throwable { 24 | this.methodInvocation.setArguments(args); 25 | return this.methodInvocation.proceed(); 26 | } 27 | 28 | @Override 29 | public Object[] getArgs() { 30 | return this.methodInvocation.getArguments().clone(); 31 | } 32 | 33 | @Override 34 | public String getMethodName() { 35 | return this.methodInvocation.getMethod().getName(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/advisor/joinpoint/ProceedingJoinPoint.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.advisor.joinpoint; 2 | 3 | /** 4 | * 就是一个 MethodInvocation, 5 | * Spring 的实现 MethodInvocationProceedingJoinPoint 中就是内置了一个 MethodInvocation 6 | * @author mafei007 7 | * @date 2022/7/8 22:48 8 | */ 9 | public interface ProceedingJoinPoint extends JoinPoint { 10 | 11 | /** 12 | * 不带参数调用proceed()将导致调用者的原始参数在调用时提供给底层方法 13 | * 14 | * @return 15 | * @throws Throwable 16 | */ 17 | Object proceed() throws Throwable; 18 | 19 | /** 20 | * 重载方法,它接受参数数组 (Object[] args)。调用时,数组中的值将用作底层方法的参数。 21 | * 可以修改实参 22 | * 23 | * @param args 24 | * @return 25 | * @throws Throwable 26 | */ 27 | Object proceed(Object[] args) throws Throwable; 28 | } 29 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/anno/After.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.anno; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author mafei007 10 | * @date 2022/7/7 20:13 11 | */ 12 | @Target(ElementType.METHOD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface After { 15 | String value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/anno/AfterAdvice.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.anno; 2 | 3 | import com.mafei.spring.aop.AspectInstanceFactory; 4 | import com.mafei.spring.aop.advisor.Advice; 5 | import com.mafei.spring.aop.advisor.CommonAdvice; 6 | import com.mafei.spring.aop.advisor.MethodInterceptor; 7 | import com.mafei.spring.aop.advisor.MethodInvocation; 8 | 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * @author mafei007 13 | * @date 2022/7/7 23:23 14 | */ 15 | public class AfterAdvice extends CommonAdvice implements Advice, MethodInterceptor { 16 | 17 | public AfterAdvice(Method aspectJAdviceMethod, AspectInstanceFactory aspectInstanceFactory) { 18 | super(aspectJAdviceMethod, aspectInstanceFactory); 19 | } 20 | 21 | /* 22 | @Override 23 | @Nullable 24 | public Object invoke(MethodInvocation mi) throws Throwable { 25 | try { 26 | return mi.proceed(); 27 | } 28 | finally { 29 | invokeAdviceMethod(getJoinPointMatch(), null, null); 30 | } 31 | } 32 | */ 33 | 34 | @Override 35 | public Object invoke(MethodInvocation invocation) throws Throwable { 36 | try { 37 | return invocation.proceed(); 38 | } finally { 39 | after(); 40 | } 41 | } 42 | 43 | public void after() throws Throwable { 44 | invokeAdviceMethod(null,null); 45 | } 46 | 47 | @Override 48 | public int getOrder() { 49 | return 1; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/anno/AfterReturning.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.anno; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author mafei007 10 | * @date 2022/7/7 23:36 11 | */ 12 | @Target(ElementType.METHOD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface AfterReturning { 15 | String value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/anno/AfterReturningAdvice.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.anno; 2 | 3 | import com.mafei.spring.aop.AspectInstanceFactory; 4 | import com.mafei.spring.aop.advisor.Advice; 5 | import com.mafei.spring.aop.advisor.CommonAdvice; 6 | import com.mafei.spring.aop.advisor.MethodInterceptor; 7 | import com.mafei.spring.aop.advisor.MethodInvocation; 8 | 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * @author mafei007 13 | * @date 2022/7/7 23:27 14 | */ 15 | public class AfterReturningAdvice extends CommonAdvice implements Advice, MethodInterceptor { 16 | 17 | public AfterReturningAdvice(Method aspectJAdviceMethod, AspectInstanceFactory aspectInstanceFactory) { 18 | super(aspectJAdviceMethod, aspectInstanceFactory); 19 | } 20 | 21 | /* 22 | @Override 23 | @Nullable 24 | public Object invoke(MethodInvocation mi) throws Throwable { 25 | Object retVal = mi.proceed(); 26 | this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); 27 | return retVal; 28 | } 29 | 30 | */ 31 | 32 | @Override 33 | public Object invoke(MethodInvocation invocation) throws Throwable { 34 | Object retVal = invocation.proceed(); 35 | afterReturning(); 36 | return retVal; 37 | } 38 | 39 | public void afterReturning() throws Throwable { 40 | invokeAdviceMethod(null,null); 41 | } 42 | 43 | @Override 44 | public int getOrder() { 45 | return 2; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/anno/AfterThrowing.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.anno; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author mafei007 10 | * @date 2022/7/7 20:13 11 | */ 12 | @Target(ElementType.METHOD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface AfterThrowing { 15 | String value() default ""; 16 | 17 | /** 18 | * 值只能是 ex,或者异常的全限定名,如 java.lang.ClassNotFoundException 19 | * 如果注解中指定了 throwing 参数,通知方法中第一个参数必须是异常类型 20 | * @return 21 | */ 22 | String throwing() default ""; 23 | } 24 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/anno/AfterThrowingAdvice.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.anno; 2 | 3 | import com.mafei.spring.aop.AspectInstanceFactory; 4 | import com.mafei.spring.aop.advisor.Advice; 5 | import com.mafei.spring.aop.advisor.CommonAdvice; 6 | import com.mafei.spring.aop.advisor.MethodInterceptor; 7 | import com.mafei.spring.aop.advisor.MethodInvocation; 8 | 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * @author mafei007 13 | * @date 2022/7/7 23:23 14 | */ 15 | public class AfterThrowingAdvice extends CommonAdvice implements Advice, MethodInterceptor { 16 | 17 | public AfterThrowingAdvice(Method aspectJAdviceMethod, AspectInstanceFactory aspectInstanceFactory) { 18 | super(aspectJAdviceMethod, aspectInstanceFactory); 19 | } 20 | 21 | @Override 22 | public void setThrowingName(String name) { 23 | super.setThrowingName(name); 24 | } 25 | 26 | /* 27 | public Object invoke(MethodInvocation mi) throws Throwable { 28 | try { 29 | return mi.proceed(); 30 | } 31 | catch (Throwable ex) { 32 | if (shouldInvokeOnThrowing(ex)) { 33 | invokeAdviceMethod(getJoinPointMatch(), null, ex); 34 | } 35 | throw ex; 36 | } 37 | } 38 | */ 39 | 40 | @Override 41 | public Object invoke(MethodInvocation invocation) throws Throwable { 42 | try { 43 | return invocation.proceed(); 44 | } catch (Throwable ex) { 45 | if (shouldInvokeOnThrowing(ex)) { 46 | afterThrowing(ex); 47 | } 48 | throw ex; 49 | } 50 | } 51 | 52 | /** 53 | * 只有当抛出的异常是给定抛出类型的子类型时,才会调用 afterThrowing 通知。 54 | * 55 | * @param ex 56 | * @return 57 | */ 58 | private boolean shouldInvokeOnThrowing(Throwable ex) { 59 | return getDiscoveredThrowingType().isAssignableFrom(ex.getClass()); 60 | } 61 | 62 | public void afterThrowing(Throwable ex) throws Throwable { 63 | invokeAdviceMethod(null, ex); 64 | } 65 | 66 | @Override 67 | public int getOrder() { 68 | return 2; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/anno/Around.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.anno; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author mafei007 10 | * @date 2022/7/7 20:13 11 | */ 12 | @Target(ElementType.METHOD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface Around { 15 | String value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/anno/AroundAdvice.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.anno; 2 | 3 | import com.mafei.spring.aop.AspectInstanceFactory; 4 | import com.mafei.spring.aop.advisor.Advice; 5 | import com.mafei.spring.aop.advisor.CommonAdvice; 6 | import com.mafei.spring.aop.advisor.MethodInterceptor; 7 | import com.mafei.spring.aop.advisor.MethodInvocation; 8 | import com.mafei.spring.aop.advisor.joinpoint.MethodInvocationProceedingJoinPoint; 9 | import com.mafei.spring.aop.advisor.joinpoint.ProceedingJoinPoint; 10 | 11 | import java.lang.reflect.Method; 12 | 13 | /** 14 | * @author mafei007 15 | * @date 2022/7/8 22:50 16 | */ 17 | public class AroundAdvice extends CommonAdvice implements Advice, MethodInterceptor { 18 | 19 | public AroundAdvice(Method aspectJAdviceMethod, AspectInstanceFactory aspectInstanceFactory) { 20 | super(aspectJAdviceMethod, aspectInstanceFactory); 21 | } 22 | 23 | /* 24 | @Override 25 | @Nullable 26 | public Object invoke(MethodInvocation mi) throws Throwable { 27 | if (!(mi instanceof ProxyMethodInvocation)) { 28 | throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi); 29 | } 30 | ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi; 31 | ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi); 32 | JoinPointMatch jpm = getJoinPointMatch(pmi); 33 | return invokeAdviceMethod(pjp, jpm, null, null); 34 | } 35 | 36 | protected ProceedingJoinPoint lazyGetProceedingJoinPoint(ProxyMethodInvocation rmi) { 37 | return new MethodInvocationProceedingJoinPoint(rmi); 38 | } 39 | */ 40 | 41 | @Override 42 | public Object invoke(MethodInvocation invocation) throws Throwable { 43 | ProceedingJoinPoint pjp = getProceedingJoinPoint(invocation); 44 | return around(pjp); 45 | } 46 | 47 | public Object around(ProceedingJoinPoint pjp) throws Throwable { 48 | return invokeAdviceMethod(pjp, null); 49 | } 50 | 51 | protected ProceedingJoinPoint getProceedingJoinPoint(MethodInvocation mi) { 52 | return new MethodInvocationProceedingJoinPoint(mi); 53 | } 54 | 55 | @Override 56 | public int getOrder() { 57 | return -1; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/anno/Aspect.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.anno; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * 指定一个类为切面类 10 | * @author mafei007 11 | * @date 2022/7/7 20:13 12 | */ 13 | @Target(ElementType.TYPE) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface Aspect { 16 | } 17 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/anno/Before.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.anno; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author mafei007 10 | * @date 2022/7/7 20:12 11 | */ 12 | @Target(ElementType.METHOD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface Before { 15 | String value(); 16 | } 17 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/anno/BeforeAdvice.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.anno; 2 | 3 | import com.mafei.spring.aop.AspectInstanceFactory; 4 | import com.mafei.spring.aop.advisor.Advice; 5 | import com.mafei.spring.aop.advisor.CommonAdvice; 6 | import com.mafei.spring.aop.advisor.MethodInterceptor; 7 | import com.mafei.spring.aop.advisor.MethodInvocation; 8 | 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * @author mafei007 13 | * @date 2022/7/7 23:00 14 | */ 15 | public class BeforeAdvice extends CommonAdvice implements Advice, MethodInterceptor { 16 | 17 | public BeforeAdvice(Method aspectJAdviceMethod, AspectInstanceFactory aspectInstanceFactory) { 18 | super(aspectJAdviceMethod, aspectInstanceFactory); 19 | } 20 | 21 | /* 22 | public Object invoke(MethodInvocation mi) throws Throwable { 23 | this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); 24 | return mi.proceed(); 25 | } 26 | */ 27 | 28 | @Override 29 | public Object invoke(MethodInvocation invocation) throws Throwable { 30 | before(); 31 | return invocation.proceed(); 32 | } 33 | 34 | public void before () throws Throwable { 35 | invokeAdviceMethod(null,null); 36 | } 37 | 38 | @Override 39 | public int getOrder() { 40 | return 0; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/proxy/AopContext.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.proxy; 2 | 3 | /** 4 | * 获取当前正在运行的 AOP 代理对象 5 | * 6 | * @author mafei007 7 | * @date 2022/7/24 23:39 8 | */ 9 | public final class AopContext { 10 | 11 | public static final ThreadLocal currentProxy = new ThreadLocal<>(); 12 | 13 | private AopContext() { 14 | } 15 | 16 | public static Object currentProxy() { 17 | Object proxy = currentProxy.get(); 18 | if (proxy == null) { 19 | throw new IllegalStateException("当前没有代理在运行"); 20 | } 21 | return proxy; 22 | } 23 | 24 | public static Object setCurrentProxy(Object proxy) { 25 | Object old = currentProxy.get(); 26 | if (proxy != null) { 27 | currentProxy.set(proxy); 28 | } else { 29 | currentProxy.remove(); 30 | } 31 | return old; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/proxy/AopProxy.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.proxy; 2 | 3 | /** 4 | * @author mafei007 5 | * @date 2022/7/8 01:14 6 | */ 7 | public interface AopProxy { 8 | 9 | Object getProxy(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/proxy/JdkDynamicAopProxy.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.proxy; 2 | 3 | import com.mafei.spring.aop.advisor.DefaultMethodInvocation; 4 | import com.mafei.spring.aop.advisor.Interceptor; 5 | import com.mafei.spring.aop.util.AopUtils; 6 | 7 | import java.lang.reflect.InvocationHandler; 8 | import java.lang.reflect.Method; 9 | import java.lang.reflect.Proxy; 10 | import java.util.List; 11 | 12 | /** 13 | * @author mafei007 14 | * @date 2022/7/8 01:16 15 | */ 16 | public class JdkDynamicAopProxy implements AopProxy, InvocationHandler { 17 | 18 | private ProxyFactory proxyFactory; 19 | private final Class[] proxiedInterfaces; 20 | 21 | public JdkDynamicAopProxy(ProxyFactory proxyFactory) { 22 | this.proxyFactory = proxyFactory; 23 | this.proxiedInterfaces = completeProxiedInterfaces(this.proxyFactory); 24 | } 25 | 26 | @Override 27 | public Object getProxy() { 28 | return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), 29 | this.proxiedInterfaces, this); 30 | } 31 | 32 | @Override 33 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 34 | Object oldProxy = null; 35 | boolean setProxyContext = false; 36 | 37 | TargetSource targetSource = this.proxyFactory.getTargetSource(); 38 | Object target = null; 39 | 40 | try { 41 | Object retVal; 42 | 43 | // 暴露当前正在运行的代理对象给 AopContext 44 | if (this.proxyFactory.exposeProxy()) { 45 | oldProxy = AopContext.setCurrentProxy(proxy); 46 | setProxyContext = true; 47 | } 48 | 49 | target = targetSource.getTarget(); 50 | Class targetClass = target.getClass(); 51 | 52 | // 得到此 method 的拦截器链,就是一堆环绕通知 53 | // 需要根据 invoke 的 method 来做进一步确定,过滤出应用在这个 method 上的 Advice 54 | List chain = this.proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 55 | 56 | if (chain.isEmpty()) { 57 | retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); 58 | } else { 59 | DefaultMethodInvocation methodInvocation = new DefaultMethodInvocation(target, method, args, chain); 60 | retVal = methodInvocation.proceed(); 61 | } 62 | 63 | // 处理特殊的返回值 this 64 | Class returnType = method.getReturnType(); 65 | if (retVal != null && retVal == target && 66 | returnType != Object.class && returnType.isInstance(proxy)) { 67 | retVal = proxy; 68 | } 69 | return retVal; 70 | } finally { 71 | if (setProxyContext) { 72 | // Restore old proxy. 73 | AopContext.setCurrentProxy(oldProxy); 74 | } 75 | } 76 | } 77 | 78 | /** 79 | * TODO 补充代理对象的接口,如 SpringProxy、Advised、DecoratingProxy 80 | * 81 | * @param proxyFactory 82 | * @return 83 | */ 84 | private Class[] completeProxiedInterfaces(ProxyFactory proxyFactory) { 85 | Class[] proxiedInterfaces = proxyFactory.getProxiedInterfaces(); 86 | return proxiedInterfaces; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/proxy/LazyInjectTargetSource.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.proxy; 2 | 3 | import com.mafei.spring.MaFeiApplicationContext; 4 | 5 | /** 6 | * 用于构造方法注入时的延迟注入 7 | * 有可能注入的是个多例 bean,所以每次都从容器中获取,不能缓存起来 8 | * 9 | * @author mafei007 10 | * @date 2022/7/24 18:13 11 | */ 12 | public class LazyInjectTargetSource implements TargetSource { 13 | 14 | private final MaFeiApplicationContext applicationContext; 15 | private final String beanName; 16 | 17 | public LazyInjectTargetSource(MaFeiApplicationContext applicationContext, String beanName) { 18 | this.applicationContext = applicationContext; 19 | this.beanName = beanName; 20 | } 21 | 22 | @Override 23 | public Object getTarget() throws Exception { 24 | return applicationContext.getBean(beanName); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/proxy/ObjenesisCglibAopProxy.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.proxy; 2 | 3 | /** 4 | * TODO 使用 cglib 动态代理 5 | * @author mafei007 6 | * @date 2022/7/8 01:16 7 | */ 8 | public class ObjenesisCglibAopProxy implements AopProxy { 9 | 10 | private ProxyFactory proxyFactory; 11 | 12 | public ObjenesisCglibAopProxy(ProxyFactory proxyFactory) { 13 | this.proxyFactory = proxyFactory; 14 | } 15 | 16 | @Override 17 | public Object getProxy() { 18 | return null; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/proxy/ProxyFactory.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.proxy; 2 | 3 | import com.mafei.spring.aop.advisor.*; 4 | 5 | import java.lang.reflect.Method; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * 实际上就是个 ProxyConfig,每个代理对象都持有一个 ProxyFactory 11 | * 一个 ProxyFactory 只能生产一个代理对象 12 | * 13 | * @author mafei007 14 | * @date 2022/7/8 00:41 15 | */ 16 | public class ProxyFactory { 17 | 18 | private List advisorList; 19 | private TargetSource targetSource; 20 | private List> interfaces; 21 | private boolean proxyTargetClass; 22 | private static final Class[] EMPTY_CLASS_ARRAY = {}; 23 | 24 | /** 25 | * 是否允许代理对象作为 ThreadLocal 通过 AopContext 访问 26 | */ 27 | private boolean exposeProxy = true; 28 | 29 | public ProxyFactory() { 30 | this.proxyTargetClass = false; 31 | this.advisorList = new ArrayList<>(); 32 | this.interfaces = new ArrayList<>(); 33 | } 34 | 35 | public void addAdvisors(List advisorList) { 36 | this.advisorList.addAll(advisorList); 37 | } 38 | 39 | public Object getProxy() { 40 | AopProxy aopProxy = createAopProxy(); 41 | return aopProxy.getProxy(); 42 | } 43 | 44 | public AopProxy createAopProxy() { 45 | if (isProxyTargetClass()) { 46 | return new ObjenesisCglibAopProxy(this); 47 | } else { 48 | // 有接口 49 | if (!this.interfaces.isEmpty()) { 50 | return new JdkDynamicAopProxy(this); 51 | } else { 52 | // 没接口 53 | return new ObjenesisCglibAopProxy(this); 54 | } 55 | } 56 | } 57 | 58 | /** 59 | * TODO 没有实现动态通知调用 60 | * 得到此 method 的拦截器链,就是一堆环绕通知 61 | * 需要根据 invoke 的 method 来做进一步确定,过滤出应用在这个 method 上的 Advice 62 | * 63 | * @param method 64 | * @param targetClass 65 | * @return 66 | */ 67 | public List getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) { 68 | List interceptorList = new ArrayList<>(this.advisorList.size()); 69 | for (Advisor advisor : this.advisorList) { 70 | MethodMatcher methodMatcher = advisor.getPointcut().getMethodMatcher(); 71 | // 切点表达式匹配才添加此 MethodInterceptor 72 | if (methodMatcher.matches(method, targetClass)) { 73 | Advice advice = advisor.getAdvice(); 74 | if (advice instanceof MethodInterceptor) { 75 | interceptorList.add((MethodInterceptor) advice); 76 | } 77 | } 78 | } 79 | return interceptorList; 80 | } 81 | 82 | public void setTarget(Object bean) { 83 | setTargetSource(new SingletonTargetSource(bean)); 84 | } 85 | 86 | public void setTargetSource(TargetSource targetSource) { 87 | this.targetSource = targetSource; 88 | } 89 | 90 | public TargetSource getTargetSource() { 91 | return targetSource; 92 | } 93 | 94 | public boolean isProxyTargetClass() { 95 | return proxyTargetClass; 96 | } 97 | 98 | public void addInterface(Class intf) { 99 | if (!intf.isInterface()) { 100 | throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface"); 101 | } 102 | // 避免重复添加相同的接口 103 | if (!this.interfaces.contains(intf)) { 104 | this.interfaces.add(intf); 105 | } 106 | } 107 | 108 | public void setInterfaces(Class... interfaces) { 109 | this.interfaces.clear(); 110 | for (Class intf : interfaces) { 111 | addInterface(intf); 112 | } 113 | } 114 | 115 | public Class[] getProxiedInterfaces() { 116 | return this.interfaces.toArray(EMPTY_CLASS_ARRAY); 117 | } 118 | 119 | public boolean exposeProxy() { 120 | return exposeProxy; 121 | } 122 | 123 | public void setExposeProxy(boolean exposeProxy) { 124 | this.exposeProxy = exposeProxy; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/proxy/SingletonTargetSource.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.proxy; 2 | 3 | /** 4 | * @author mafei007 5 | * @date 2022/7/24 18:09 6 | */ 7 | public class SingletonTargetSource implements TargetSource { 8 | 9 | private final Object target; 10 | 11 | public SingletonTargetSource(Object target) { 12 | this.target = target; 13 | } 14 | 15 | @Override 16 | public Object getTarget() throws Exception { 17 | return this.target; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/proxy/TargetSource.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.proxy; 2 | 3 | /** 4 | * 用于获取AOP调用的当前“目标” 5 | * 6 | * @author mafei007 7 | * @date 2022/7/24 18:05 8 | */ 9 | public interface TargetSource { 10 | 11 | Object getTarget() throws Exception; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/com/mafei/spring/aop/util/AopUtils.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.aop.util; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * @author mafei007 8 | * @date 2022/7/8 01:57 9 | */ 10 | public class AopUtils { 11 | public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args) throws Throwable { 12 | try { 13 | return method.invoke(target, args); 14 | } catch (IllegalAccessException e) { 15 | throw e; 16 | } catch (InvocationTargetException e) { 17 | throw e.getTargetException(); 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/com/mafei/spring/core/OrderComparator.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.core; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | import java.util.List; 6 | 7 | /** 8 | * @author mafei007 9 | * @date 2022/7/9 01:47 10 | */ 11 | public class OrderComparator implements Comparator { 12 | 13 | public static final OrderComparator INSTANCE = new OrderComparator(); 14 | 15 | public static void sort(List list) { 16 | if (list.size() > 1) { 17 | list.sort(INSTANCE); 18 | } 19 | } 20 | 21 | public static void sort(Object[] array) { 22 | if (array.length > 1) { 23 | Arrays.sort(array, INSTANCE); 24 | } 25 | } 26 | 27 | @Override 28 | public int compare(Object o1, Object o2) { 29 | boolean p1 = o1 instanceof PriorityOrdered; 30 | boolean p2 = o2 instanceof PriorityOrdered; 31 | if (p1 && !p2) { 32 | return -1; 33 | } else if (!p1 && p2) { 34 | return 1; 35 | } 36 | int order1 = getOrder(o1); 37 | int order2 = getOrder(o2); 38 | // 不要直接写 order1 - order2, 会照成数值溢出问题 39 | // 使用 Integer.compare 避免溢出 40 | return Integer.compare(order1, order2); 41 | } 42 | 43 | private int getOrder(Object obj) { 44 | if (obj == null) { 45 | return Ordered.LOWEST_PRECEDENCE; 46 | } 47 | if (obj instanceof Ordered) { 48 | return ((Ordered) obj).getOrder(); 49 | } else { 50 | return Ordered.LOWEST_PRECEDENCE; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/mafei/spring/core/Ordered.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.core; 2 | 3 | public interface Ordered { 4 | 5 | /** 6 | * Useful constant for the highest precedence value. 7 | * @see java.lang.Integer#MIN_VALUE 8 | */ 9 | int HIGHEST_PRECEDENCE = Integer.MIN_VALUE; 10 | 11 | /** 12 | * Useful constant for the lowest precedence value. 13 | * @see java.lang.Integer#MAX_VALUE 14 | */ 15 | int LOWEST_PRECEDENCE = Integer.MAX_VALUE; 16 | 17 | 18 | /** 19 | * Get the order value of this object. 20 | *

Higher values are interpreted as lower priority. As a consequence, 21 | * the object with the lowest value has the highest priority (somewhat 22 | * analogous to Servlet {@code load-on-startup} values). 23 | *

Same order values will result in arbitrary sort positions for the 24 | * affected objects. 25 | * @return the order value 26 | * @see #HIGHEST_PRECEDENCE 27 | * @see #LOWEST_PRECEDENCE 28 | */ 29 | int getOrder(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/com/mafei/spring/core/PriorityOrdered.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.core; 2 | 3 | /** 4 | * Extension of the {@link Ordered} interface, expressing a priority 5 | * ordering: {@code PriorityOrdered} objects are always applied before 6 | * plain {@link Ordered} objects regardless of their order values. 7 | * 8 | *

When sorting a set of {@code Ordered} objects, {@code PriorityOrdered} 9 | * objects and plain {@code Ordered} objects are effectively treated as 10 | * two separate subsets, PriorityOrdered 对象集位于纯 Ordered 对象集之前,并在这些子集内应用相对排序。 11 | */ 12 | public interface PriorityOrdered extends Ordered { 13 | } -------------------------------------------------------------------------------- /src/com/mafei/spring/interfaces/ApplicationContextAware.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.interfaces; 2 | 3 | import com.mafei.spring.MaFeiApplicationContext; 4 | 5 | /** 6 | * @author mafei007 7 | * @date 2022/7/8 02:38 8 | */ 9 | public interface ApplicationContextAware { 10 | 11 | void setApplicationContext(MaFeiApplicationContext applicationContext); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/com/mafei/spring/interfaces/BeanNameAware.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.interfaces; 2 | 3 | /** 4 | * 将 beanName 传递给 bean 5 | * 某个bean 实现了这个接口,就能得到它的 beanName 6 | * 由 Spring 调用 7 | * 8 | * @author mafei007 9 | * @date 2022/6/29 23:10 10 | */ 11 | public interface BeanNameAware { 12 | 13 | void setBeanName(String beanName); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/com/mafei/spring/interfaces/BeanPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.interfaces; 2 | 3 | /** 4 | * 在 bean 初始化前后对其进行一些操作,使程序员可以干涉 bean 初始化的过程 5 | *

6 | * 可以对 bean 进行功能扩展、增强 7 | *

8 | * AOP 就是在这里进行 9 | * AOP : 返回一个代理对象 10 | * @author mafei007 11 | * @date 2022/6/29 23:23 12 | */ 13 | public interface BeanPostProcessor { 14 | 15 | default Object postProcessBeforeInitialization(Object bean, String beanName) { 16 | return bean; 17 | } 18 | 19 | default Object postProcessAfterInitialization(Object bean, String beanName) { 20 | return bean; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/com/mafei/spring/interfaces/DisposableBean.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.interfaces; 2 | 3 | /** 4 | * @author mafei007 5 | * @date 2022/7/29 19:03 6 | */ 7 | public interface DisposableBean { 8 | void destroy() throws Exception; 9 | } 10 | -------------------------------------------------------------------------------- /src/com/mafei/spring/interfaces/InitializingBean.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.interfaces; 2 | 3 | /** 4 | * @author mafei007 5 | * @date 2022/6/29 23:18 6 | */ 7 | public interface InitializingBean { 8 | void afterPropertiesSet(); 9 | } 10 | -------------------------------------------------------------------------------- /src/com/mafei/spring/interfaces/ObjectFactory.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.interfaces; 2 | 3 | /** 4 | * @author mafei007 5 | * @date 2022/7/23 16:52 6 | */ 7 | @FunctionalInterface 8 | public interface ObjectFactory { 9 | T getObject() throws RuntimeException; 10 | } 11 | -------------------------------------------------------------------------------- /src/com/mafei/spring/interfaces/SmartInstantiationAwareBeanPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.mafei.spring.interfaces; 2 | 3 | /** 4 | * 用于发生循环依赖时,提前对 bean 创建代理对象,这样注入的就是代理对象,而不是原始对象 5 | * @author mafei007 6 | * @date 2022/7/23 17:34 7 | */ 8 | public interface SmartInstantiationAwareBeanPostProcessor extends BeanPostProcessor { 9 | 10 | /** 11 | * 如果 bean 需要被代理,返回代理对象;不需要被代理直接返回原始对象。 12 | * @param bean 13 | * @param beanName 14 | * @return 15 | * @throws RuntimeException 16 | */ 17 | default Object getEarlyBeanReference(Object bean, String beanName) throws RuntimeException { 18 | return bean; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/com/mafei/test/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test; 2 | 3 | import com.mafei.spring.anno.ComponentScan; 4 | 5 | /** 6 | * @author mafei007 7 | * @date 2022/6/29 19:29 8 | */ 9 | @ComponentScan("com.mafei.test") 10 | public class AppConfig { 11 | } 12 | -------------------------------------------------------------------------------- /src/com/mafei/test/MyAspect.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test; 2 | 3 | import com.mafei.spring.anno.Component; 4 | import com.mafei.spring.aop.advisor.joinpoint.ProceedingJoinPoint; 5 | import com.mafei.spring.aop.anno.*; 6 | 7 | /** 8 | * @author mafei007 9 | * @date 2022/7/8 02:43 10 | */ 11 | @Aspect 12 | @Component 13 | public class MyAspect { 14 | 15 | @Around("execution(* *.UserService.*())") 16 | public Object f5(ProceedingJoinPoint pjp) { 17 | Object[] args = pjp.getArgs(); 18 | String methodName = pjp.getMethodName(); 19 | if (methodName.equals("test")) { 20 | args[0] = 200; 21 | } 22 | Object retVal = null; 23 | try { 24 | System.out.println("环绕通知 before ..."); 25 | // 调用执行链 26 | retVal = pjp.proceed(args); 27 | System.out.println("环绕通知 after returning ..."); 28 | return retVal; 29 | } catch (Throwable e) { 30 | System.out.println("环绕通知 after throwing...😡😡" + e); 31 | throw new RuntimeException(e); 32 | } finally { 33 | System.out.println("环绕通知 after ..."); 34 | } 35 | } 36 | 37 | 38 | @Before("execution(* *.UserService.*())") 39 | public void f1() { 40 | System.out.println("before 1 通知...."); 41 | } 42 | 43 | @After("execution(* *.UserService.*())") 44 | public void f2() { 45 | System.out.println("after 通知...."); 46 | } 47 | 48 | 49 | // @Before("execution(* *.UserService.*())") 50 | // public void f3() { 51 | // System.out.println("before 2 通知...."); 52 | // } 53 | 54 | 55 | @AfterReturning("execution(* *.UserService.*())") 56 | public void f4() { 57 | System.out.println("AfterReturning 1 通知...."); 58 | } 59 | 60 | 61 | // @AfterReturning("execution(* *.UserService.*())") 62 | // public void f5() { 63 | // System.out.println("AfterReturning 2 通知...."); 64 | // } 65 | 66 | @AfterThrowing(value = "execution(* *.UserService.*())", throwing = "ex") 67 | public void throwing1(ArithmeticException ex) { 68 | System.out.println("\uD83D\uDE21\uD83D\uDE21\uD83D\uDE21 throwing....拦截算术异常:" + ex); 69 | } 70 | 71 | @AfterThrowing(value = "execution(* *.UserService.*())") 72 | public void throwing2() { 73 | System.out.println("\uD83D\uDE21\uD83D\uDE21\uD83D\uDE21 throwing....出异常了, @AfterThrowing 拦截了这个全局异常"); 74 | } 75 | 76 | @AfterThrowing(value = "execution(* *.UserService.*())", throwing = "java.lang.NullPointerException") 77 | public void throwing3(NullPointerException ex) { 78 | System.out.println("\uD83D\uDE21\uD83D\uDE21\uD83D\uDE21 throwing....拦截空指针异常:" + ex); 79 | } 80 | 81 | 82 | @AfterThrowing(value = "execution(* *.UserService.*())", throwing = "ex") 83 | public void throwing4(Throwable e) { 84 | System.out.println("\uD83D\uDE21\uD83D\uDE21\uD83D\uDE21 throwing....拦截 Throwable:" + e); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/com/mafei/test/MyAspect2.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test; 2 | 3 | import com.mafei.spring.anno.Component; 4 | import com.mafei.spring.aop.anno.After; 5 | import com.mafei.spring.aop.anno.AfterReturning; 6 | import com.mafei.spring.aop.anno.Aspect; 7 | import com.mafei.spring.aop.anno.Before; 8 | 9 | /** 10 | * @author mafei007 11 | * @date 2022/7/8 03:52 12 | */ 13 | @Aspect 14 | @Component 15 | public class MyAspect2 { 16 | 17 | @Before("execution(* *.PostService.*())") 18 | public void f3() { 19 | System.out.println("before 2 通知...."); 20 | } 21 | 22 | 23 | @AfterReturning("execution(* *.PostService.*())") 24 | public void f4() { 25 | System.out.println("AfterReturning 1 通知...."); 26 | } 27 | 28 | 29 | @AfterReturning("execution(* *.PostService.*())") 30 | public void f5() { 31 | System.out.println("AfterReturning 2 通知...."); 32 | } 33 | 34 | @Before("execution(* *.PostService.*())") 35 | public void f1() { 36 | System.out.println("before 1 通知...."); 37 | } 38 | 39 | @After("execution(* *.PostService.*())") 40 | public void f2() { 41 | System.out.println("after 通知...."); 42 | } 43 | 44 | 45 | 46 | @After("execution(* *.UserService.*())") 47 | public void f11() { 48 | System.out.println("after 通知 in Aspect2 ...."); 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/com/mafei/test/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test; 2 | 3 | import com.mafei.spring.anno.Component; 4 | 5 | /** 6 | * @author mafei007 7 | * @date 2022/6/29 22:46 8 | */ 9 | @Component 10 | public class OrderService { 11 | } 12 | -------------------------------------------------------------------------------- /src/com/mafei/test/PostInterface.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test; 2 | 3 | /** 4 | * @author mafei007 5 | * @date 2022/7/8 03:50 6 | */ 7 | public interface PostInterface { 8 | 9 | void post(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/com/mafei/test/PostService.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test; 2 | 3 | import com.mafei.spring.anno.Component; 4 | 5 | /** 6 | * @author mafei007 7 | * @date 2022/7/8 03:50 8 | */ 9 | @Component 10 | public class PostService implements PostInterface { 11 | @Override 12 | public void post() { 13 | System.out.println("post........"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/com/mafei/test/Test.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test; 2 | 3 | import com.mafei.spring.MaFeiApplicationContext; 4 | 5 | /** 6 | * @author mafei007 7 | * @date 2022/6/29 19:27 8 | */ 9 | public class Test { 10 | public static void main(String[] args) { 11 | MaFeiApplicationContext applicationContext = new MaFeiApplicationContext(AppConfig.class); 12 | 13 | System.out.println("=================beanNames================="); 14 | for (String beanName : applicationContext.getBeanNames()) { 15 | System.out.println(beanName); 16 | } 17 | System.out.println("==========================================="); 18 | 19 | // JDK 代理对象返回的是 com.sun.proxy.$Proxy5, 不能强转为实现,只能强转为接口 20 | // UserService userService = (UserService) applicationContext.getBean("userService"); 21 | UserInterface userService = (UserInterface) applicationContext.getBean("userService"); 22 | System.out.println("userService: " + userService.getClass().getName()); 23 | userService.test(100); 24 | System.out.println("applicationContext.getBean(\"orderService\"): " + applicationContext.getBean("orderService")); 25 | System.out.println(">>>>>>>>>>>>>>>>>>>>>>>"); 26 | userService.toString(); 27 | 28 | // PostInterface postService = (PostInterface) applicationContext.getBean("postService"); 29 | // postService.post(); 30 | // System.out.println(postService.getClass().getName()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/com/mafei/test/TestBeanPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test; 2 | 3 | import com.mafei.spring.anno.Component; 4 | import com.mafei.spring.interfaces.BeanPostProcessor; 5 | 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.Method; 8 | import java.lang.reflect.Proxy; 9 | 10 | /** 11 | * @author mafei007 12 | * @date 2022/6/29 23:27 13 | */ 14 | // @Component 15 | public class TestBeanPostProcessor implements BeanPostProcessor { 16 | @Override 17 | public Object postProcessBeforeInitialization(Object bean, String beanName) { 18 | return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); 19 | } 20 | 21 | @Override 22 | public Object postProcessAfterInitialization(Object bean, String beanName) { 23 | // aop 24 | /*if (beanName.equals("userService")) { 25 | Object proxyInstance = Proxy.newProxyInstance(TestBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() { 26 | @Override 27 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 28 | System.out.println(bean.getClass().getName() + "." + method.getName() + ", 切面逻辑..."); 29 | return method.invoke(bean, args); 30 | } 31 | }); 32 | return proxyInstance; 33 | }*/ 34 | System.out.println("🐷🐷 BeanPostProcessor: " + beanName); 35 | return bean; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/com/mafei/test/UserInterface.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test; 2 | 3 | /** 4 | * @author mafei007 5 | * @date 2022/6/29 23:42 6 | */ 7 | public interface UserInterface { 8 | void test(int i); 9 | } 10 | -------------------------------------------------------------------------------- /src/com/mafei/test/UserService.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test; 2 | 3 | import com.mafei.spring.anno.Autowired; 4 | import com.mafei.spring.anno.Component; 5 | import com.mafei.spring.anno.Scope; 6 | import com.mafei.spring.interfaces.BeanNameAware; 7 | import com.mafei.spring.interfaces.InitializingBean; 8 | 9 | /** 10 | * @author mafei007 11 | * @date 2022/6/29 19:31 12 | */ 13 | @Component("userService") 14 | @Scope("singleton") 15 | // @Scope("prototype") 16 | public class UserService implements BeanNameAware, InitializingBean, UserInterface { 17 | 18 | @Autowired 19 | private OrderService orderService; 20 | 21 | @Override 22 | public void test(int i) { 23 | int k = 1 / 0; 24 | // String a = null; 25 | // System.out.println(a.length()); 26 | System.out.println("userService#test 方法执行。。。。。参数 i 为:" + i + "。 依赖注入的 OrderService:" + orderService); 27 | } 28 | 29 | @Override 30 | public void setBeanName(String beanName) { 31 | System.out.println("我是:" + this.getClass().getName() + ",我的 beanName是:" + beanName); 32 | } 33 | 34 | @Override 35 | public void afterPropertiesSet() { 36 | System.out.println("我是:" + this.getClass().getName() + ",开始执行初始化方法:afterPropertiesSet()"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/mafei/test/circular_references/A.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test.circular_references; 2 | 3 | import com.mafei.spring.anno.Autowired; 4 | import com.mafei.spring.anno.Component; 5 | import com.mafei.spring.anno.Lazy; 6 | import com.mafei.spring.anno.Scope; 7 | import com.mafei.spring.interfaces.DisposableBean; 8 | import com.mafei.spring.interfaces.InitializingBean; 9 | import com.mafei.spring.interfaces.ObjectFactory; 10 | 11 | /** 12 | * @author mafei007 13 | * @date 2022/7/23 16:27 14 | */ 15 | // @Scope("prototype") 16 | @Component 17 | public class A implements MyInterface, InitializingBean, DisposableBean { 18 | 19 | /** 20 | * 采用 jdk 动态代理,注入的类型需要是接口类型 21 | */ 22 | // @Autowired 23 | private MyInterface b; 24 | 25 | private ObjectFactory bObj; 26 | 27 | // public A(@Lazy MyInterface b) { 28 | // // public A(ObjectFactory b) { 29 | // this.b = b; 30 | // // this.bObj = b; 31 | // System.out.println("A 创建,构造注入的 b 为:" + b.getClass()); 32 | // } 33 | 34 | 35 | public A() { 36 | System.out.println("A 创建"); 37 | } 38 | 39 | @Override 40 | public void afterPropertiesSet() { 41 | System.out.println("A 初始化"); 42 | } 43 | 44 | 45 | @Override 46 | public void foo() { 47 | System.out.println("【【【【【【【【【【【【【【【【【A.foo start】......." + this.b.getClass()); 48 | this.b.foo(); 49 | // this.bObj.getObject().foo(); 50 | System.out.println("【【【【【【【【【【【【【【【【【A.foo end】"); 51 | } 52 | 53 | @Autowired 54 | public void setB(MyInterface b) { 55 | System.out.println("A 😋😋😋😋 依赖注入 setB(" + b.getClass().getName() + ")"); 56 | this.b = b; 57 | } 58 | 59 | @Override 60 | public void destroy() throws Exception { 61 | System.out.println("A destroy..."); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/com/mafei/test/circular_references/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test.circular_references; 2 | 3 | import com.mafei.spring.anno.ComponentScan; 4 | 5 | /** 6 | * @author mafei007 7 | * @date 2022/7/23 16:25 8 | */ 9 | @ComponentScan("com.mafei.test.circular_references") 10 | public class AppConfig { 11 | } 12 | -------------------------------------------------------------------------------- /src/com/mafei/test/circular_references/B.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test.circular_references; 2 | 3 | import com.mafei.spring.anno.Autowired; 4 | import com.mafei.spring.anno.Component; 5 | import com.mafei.spring.anno.Lazy; 6 | import com.mafei.spring.anno.Scope; 7 | import com.mafei.spring.interfaces.InitializingBean; 8 | 9 | /** 10 | * @author mafei007 11 | * @date 2022/7/23 16:29 12 | */ 13 | // @Scope("prototype") 14 | @Component 15 | public class B implements MyInterface, InitializingBean, AutoCloseable { 16 | 17 | /** 18 | * 采用 jdk 动态代理,注入的类型需要是接口类型 19 | */ 20 | // @Autowired 21 | private MyInterface a; 22 | 23 | public B(@Lazy MyInterface a) { 24 | this.a = a; 25 | System.out.println("B 创建,构造注入的 a 为:" + a.getClass()); 26 | } 27 | 28 | public B() { 29 | System.out.println("B 创建"); 30 | } 31 | 32 | @Override 33 | public void afterPropertiesSet() { 34 | System.out.println("B 初始化"); 35 | } 36 | 37 | 38 | @Override 39 | public void foo() { 40 | System.out.println("B.foo"); 41 | } 42 | 43 | @Autowired 44 | public void setA(MyInterface a) { 45 | System.out.println("B 😋😋😋😋 依赖注入 setA(" + a.getClass().getName() + ")"); 46 | this.a = a; 47 | } 48 | 49 | @Override 50 | public void close() throws Exception { 51 | System.out.println("B destroy by AutoCloseable..."); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/mafei/test/circular_references/C.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test.circular_references; 2 | 3 | import com.mafei.spring.anno.Autowired; 4 | import com.mafei.spring.anno.Component; 5 | import com.mafei.spring.anno.Lazy; 6 | import com.mafei.spring.anno.Scope; 7 | import com.mafei.spring.interfaces.InitializingBean; 8 | 9 | /** 10 | * @author mafei007 11 | * @date 2022/7/25 03:07 12 | */ 13 | @Scope("prototype") 14 | // @Component 15 | public class C implements MyInterface, InitializingBean { 16 | 17 | /** 18 | * 采用 jdk 动态代理,注入的类型需要是接口类型 19 | */ 20 | // @Autowired 21 | private MyInterface d; 22 | 23 | public C(@Lazy MyInterface d) { 24 | this.d = d; 25 | System.out.println("C 创建,构造注入的 d 为:" + d.getClass()); 26 | } 27 | 28 | @Override 29 | public void afterPropertiesSet() { 30 | System.out.println("C 初始化"); 31 | } 32 | 33 | @Override 34 | public void foo() { 35 | System.out.println("【【【【【【【【【【【【【【【【【C.foo start】......." + this.d.getClass()); 36 | this.d.foo(); 37 | System.out.println("【【【【【【【【【【【【【【【【【C.foo end】"); 38 | } 39 | 40 | @Autowired 41 | public void setD(MyInterface d) { 42 | System.out.println("C 😋😋😋😋 依赖注入 setD(" + d.getClass().getName() + ")"); 43 | this.d = d; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/com/mafei/test/circular_references/D.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test.circular_references; 2 | 3 | import com.mafei.spring.anno.Autowired; 4 | import com.mafei.spring.anno.Component; 5 | import com.mafei.spring.anno.Lazy; 6 | import com.mafei.spring.anno.Scope; 7 | import com.mafei.spring.interfaces.InitializingBean; 8 | 9 | /** 10 | * @author mafei007 11 | * @date 2022/7/25 03:07 12 | */ 13 | // @Scope("prototype") 14 | // @Component 15 | public class D implements MyInterface, InitializingBean { 16 | 17 | /** 18 | * 采用 jdk 动态代理,注入的类型需要是接口类型 19 | */ 20 | // @Autowired 21 | private MyInterface c; 22 | 23 | public D(MyInterface c) { 24 | this.c = c; 25 | System.out.println("D 创建,构造注入的 c 为:" + c.getClass()); 26 | } 27 | 28 | @Override 29 | public void afterPropertiesSet() { 30 | System.out.println("D 初始化"); 31 | } 32 | 33 | @Override 34 | public void foo() { 35 | System.out.println("【【【【【【【【【【【【【【【【【D.foo start】......." + this.c.getClass()); 36 | // this.c.foo(); 37 | System.out.println("【【【【【【【【【【【【【【【【【D.foo end】"); 38 | } 39 | 40 | @Autowired 41 | public void setC(MyInterface c) { 42 | System.out.println("D 😋😋😋😋 依赖注入 setC(" + c.getClass().getName() + ")"); 43 | this.c = c; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/com/mafei/test/circular_references/MyAspect.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test.circular_references; 2 | 3 | import com.mafei.spring.anno.Component; 4 | import com.mafei.spring.aop.anno.After; 5 | import com.mafei.spring.aop.anno.Aspect; 6 | import com.mafei.spring.aop.anno.Before; 7 | 8 | /** 9 | * @author mafei007 10 | * @date 2022/7/24 00:07 11 | */ 12 | @Aspect 13 | @Component 14 | public class MyAspect { 15 | 16 | @Before("execution(* *.(A|B).*())") 17 | public void before01() { 18 | System.out.println("before01..."); 19 | } 20 | 21 | @After("execution(* *.(A|B).*())") 22 | public void after01() { 23 | System.out.println("after01..."); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/com/mafei/test/circular_references/MyInterface.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test.circular_references; 2 | 3 | /** 4 | * @author mafei007 5 | * @date 2022/7/23 16:26 6 | */ 7 | public interface MyInterface { 8 | void foo(); 9 | } 10 | -------------------------------------------------------------------------------- /src/com/mafei/test/circular_references/Test.java: -------------------------------------------------------------------------------- 1 | package com.mafei.test.circular_references; 2 | 3 | import com.mafei.spring.MaFeiApplicationContext; 4 | 5 | /** 6 | * @author mafei007 7 | * @date 2022/7/23 16:25 8 | */ 9 | public class Test { 10 | 11 | public static void main(String[] args) { 12 | MaFeiApplicationContext applicationContext = new MaFeiApplicationContext(AppConfig.class); 13 | MyInterface a = applicationContext.getBean("a", MyInterface.class); 14 | a.foo(); 15 | MyInterface b = applicationContext.getBean("b", MyInterface.class); 16 | b.foo(); 17 | System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 18 | // MyInterface c = applicationContext.getBean("c", MyInterface.class); 19 | // c.foo(); 20 | applicationContext.close(); 21 | System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 22 | // applicationContext.destroyBean(a); 23 | // applicationContext.destroyBean(b); 24 | } 25 | 26 | } 27 | --------------------------------------------------------------------------------