浅谈基于动态代理的Spring AOP原理
1 什么时候会用到AOP?
- Bean的创建和初始化过程中
- 增加环绕、前置、后置方法
- 事务、日志
- 拦截器
- …
这篇文章就着重讲解下Bean创建和初始化的过程中使用到的AOP原理
2 回顾Bean的创建过程
在Bean的创建过程中比较重要的一步就是对Bean进行AOP处理,但是不是必要的,接下来我们从头开始手写一个自己的Spring进行实现。
3 扫描Bean
这里的流程主要是new一个ApplicationContext,传入xml文件或配置类,以此来扫描固定包下的类。
/** * 构造方法 * * @param configClass */ public MyApplicationContext(Class configClass) { this.configClass = configClass; //扫描Bean scanBean(); //根据BeanDefinition创建Bean for (Map.Entry<String, MyBeanDefinition> beanDefinitionEntry : beanDefinitionMap.entrySet()) { String key = beanDefinitionEntry.getKey(); MyBeanDefinition value = beanDefinitionEntry.getValue(); if (ScopeUtils.SINGLETON.equals(value.getScope())) { Object bean = createBean(key,value); singletonPool.put(key, bean); } } } /** * 扫描Bean */ private void scanBean() { //拿到配置类之后对其进行解析 扫描 MyComponentScan scan = (MyComponentScan) configClass.getDeclaredAnnotation(MyComponentScan.class); String path = scan.value(); //根据路径进行扫描 ClassLoader classLoader = MyComponentScan.class.getClassLoader(); String newPath = path.replace('.', '/'); //获取文件路径 URL url = classLoader.getResource(newPath); File file = new File(url.getFile()); if (file.isDirectory()) { File[] files = file.listFiles(); //获取到该包下的每个文件(Class) for (File f : files) { String absolutePath = f.getAbsolutePath(); //判断是不是.class文件 if (absolutePath.endsWith(".class")) { String className = absolutePath.substring(absolutePath.indexOf("org"), absolutePath.indexOf(".class")); String name = className.replace("\\", "."); try { Class<?> clazz = classLoader.loadClass(name); //判断是否有MyComponent注解 if (clazz.isAnnotationPresent(MyComponent.class)) { MyComponent component = clazz.getDeclaredAnnotation(MyComponent.class); String beanName = component.value(); if (beanName.getBytes().length == 0) { beanName = name.substring(name.lastIndexOf(".") + 1); beanName = beanName.substring(0, 1).toLowerCase(Locale.ROOT) + beanName.substring(1); } MyBeanDefinition beanDefinition = new MyBeanDefinition(); beanDefinition.setClazz(clazz); //判断bean的作用域 if (clazz.isAnnotationPresent(MyScope.class)) { MyScope scope = clazz.getDeclaredAnnotation(MyScope.class); beanDefinition.setScope(scope.value()); } else { beanDefinition.setScope("singleton"); } //判断是否实现了BeanPostProcessor if (MyBeanPostProcessor.class.isAssignableFrom(clazz)) { //这一步简化,非spring源码 MyBeanPostProcessor instance = (MyBeanPostProcessor) clazz.getDeclaredConstructor().newInstance(); beanPostProcessorList.add(instance); } //将该bean的Definition放入map中 beanDefinitionMap.put(beanName, beanDefinition); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } } }
4 创建Bean
/** * 创建bean * * @param beanDefinition * @return */ public Object createBean(String beanName,MyBeanDefinition beanDefinition) { Class clazz = beanDefinition.getClazz(); Object newInstance = null; try { newInstance = clazz.getConstructor().newInstance(); //处理依赖注入 for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(MyAutowired.class)) { Object bean = getBean(field.getName()); field.setAccessible(true); field.set(newInstance, bean); } } //BeanPostProcessor初始化前 for (MyBeanPostProcessor processor : beanPostProcessorList) { //放入的和传出的不一定是同一个对象 newInstance = processor.postProcessBeforeInitialization(newInstance, beanName); } //Bean的初始化方法 if (newInstance instanceof MyInitializingBean) { ((MyInitializingBean) newInstance).afterPropertiesSet(); } //BeanPostProcessor初始化后 for (MyBeanPostProcessor processor : beanPostProcessorList) { //放入的和传出的不一定是同一个对象 newInstance = processor.postProcessAfterInitialization(newInstance, beanName); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return newInstance; }
5 获取Bean
/** * getBean方法 * * @param beanName * @return */ public Object getBean(String beanName) { if (beanDefinitionMap.containsKey(beanName)) { MyBeanDefinition beanDefinition = beanDefinitionMap.get(beanName); if (ScopeUtils.SINGLETON.equals(beanDefinition.getScope())) { return singletonPool.get(beanName); } else { return createBean(beanName,beanDefinition); } } else { throw new MyNoSuchBeanDefinitionException("没有这个Bean"); } }
6 实现自己的BeanPostProcessor
Spring初始化Bean时对Bean的增强就是在BeanPostProcess方法中进行实现的,postProcessBeforeInitialization做前置处理,postProcessAfterInitialization做后置处理。可以看下Spring源码
/** * @desc: BeanPostProcessor抽象 * @author: YanMingXin * @create: 2021/9/16-15:01 **/ public interface MyBeanPostProcessor { Object postProcessBeforeInitialization(Object bean,String beanName); Object postProcessAfterInitialization(Object bean,String beanName); }
实现该方法,使用JDK动态代理将Bean包装
/** * @desc: MyBeanPostProcessorHandler * @author: YanMingXin * @create: 2021/9/17-10:25 **/ @MyComponent public class MyBeanPostProcessorHandler implements MyBeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { if ("studentServiceImpl".equals(beanName)) { System.out.println("初始化前"); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if ("studentServiceImpl".equals(beanName)) { Object proxyInstance = Proxy.newProxyInstance(MyBeanPostProcessorHandler.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //代理逻辑 System.out.println("代理逻辑"); //对象的方法 return method.invoke(bean, args); } }); System.out.println("初始化后"); return proxyInstance; } return bean; } }
7 测试