看过了前面的Spring Beans相关的 IOC 功能, 接下来我们来看看 AOP 是如何实现的
我们都知道 AOP 是通过动态代理来实现的, 但是代理这一步是如何实现的呢? 其实就是之前提到过的, 在Spring Bean的创建过程中, 实现BeanPostProcessor的接口可以对创建好的Bean进行修改替换等操作
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {invokeAwareMethods(beanName, bean);
 Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
 invokeInitMethods(beanName, wrappedBean, mbd);
 
 
 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
 return wrappedBean;
 }
 
 | 
下面来具体看一下实现方式
Spring AOP的基本接口是 Advisor, 它持有一个 AOP Advice「在joinpoint处要执行的增强行为」, 同时还持有一个决定 Advice是否适用的过滤器, 如pointcut;  也就是说 Advisor决定是否要对某个方法进行增强以及增强的具体逻辑实现是什么

还有一个我们需要注意的接口就是Interceptor, 这个接口继承了Advice, 也就是说它是用来对方法进行修改增强的, 它还有一些子类, 如MethodBeforeAdviceInterceptor用来在方法执行前进行处理, MethodInterceptor用来在方法执行前后进行自定义逻辑处理
当定义好了 Advisor后, 需要一个类来负责在创建bean的时候用所有的Advisor进行匹配并生成对应的代理类返回, 这个类就是AbstractAutoProxyCreator的实现类, 它继承了BeanPostProcessor接口,在创建bean的过程中进行拦截处理
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 
 | @Override
 public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
 if (bean != null) {
 Object cacheKey = getCacheKey(bean.getClass(), beanName);
 if (this.earlyProxyReferences.remove(cacheKey) != bean) {
 
 return wrapIfNecessary(bean, beanName, cacheKey);
 }
 }
 return bean;
 }
 
 protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
 return bean;
 }
 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
 return bean;
 }
 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
 this.advisedBeans.put(cacheKey, Boolean.FALSE);
 return bean;
 }
 
 
 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
 if (specificInterceptors != DO_NOT_PROXY) {
 this.advisedBeans.put(cacheKey, Boolean.TRUE);
 
 Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
 this.proxyTypes.put(cacheKey, proxy.getClass());
 return proxy;
 }
 
 this.advisedBeans.put(cacheKey, Boolean.FALSE);
 return bean;
 }
 
 | 
现在写一个例子代码来感受一下, 验证一下前面的结论
首先创建一个正常的服务
| 12
 3
 4
 5
 
 | public class DemoService {public void service() {
 System.out.println("this is demoService");
 }
 }
 
 | 
创建Advice类
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | public class LogAdvice implements MethodInterceptor {@Override
 public Object invoke(MethodInvocation invocation) throws Throwable {
 long st = System.nanoTime();
 Object result = invocation.proceed();
 System.out.println("cost time: " + (System.nanoTime() - st));
 return result;
 }
 }
 
 | 
定义配置文件
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | <bean id="logAdvice" class="com.demo.spring.advice.LogAdvice"/><bean id="demoService" class="com.demo.spring.service.DemoService"/>
 
 
 <bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
 
 <property name="advice" ref="logAdvice"/>
 
 <property name="pattern" value="com.demo.spring.service.*" />
 </bean>
 
 
 <bean class="org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator"/>
 
 | 
测试方法如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | public class Main {public static void main(String[] args) {
 ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
 DemoService demoService = applicationContext.getBean(DemoService.class);
 demoService.service();
 }
 }
 
 
 
 
 
 | 
当然我们也可以使用aop标签来简化配置文件
| 12
 3
 4
 5
 6
 
 | <aop:config proxy-target-class="false"><aop:pointcut id="service"
 expression="execution(* com.demo.spring.service..*(..)))"/>
 <aop:advisor advice-ref="logAdvice"
 pointcut-ref="service"/>
 </aop:config>
 
 | 
执行结果是一样的, 只是这种配置会自动注册AspectJAwareAdvisorAutoProxyCreator Bean, Advisor等, 具体可以参数 AopNamespaceHandler类
参考资料: Spring AOP 源码解析