首先我们创建一个例子
创建要织入的类
@Service
public class UserService {
public void login() {
System.out.println("登陆");
}
}
创建切面
这里需要加上@Component注解,以便被spring扫描到
@Aspect表示这个是一个切面
@Aspect
@Component
public class UserServiceAop {
@Pointcut("execution(* techermanager.Service.*.*(..))")
private void log(){
}
@Before("techermanager.controller.aspect.UserServiceAop.log()")
private void beforeLog(){
System.out.println("before");
}
}
在spring的xml配置文件里面加上配置
<!-- 启用aspect注解 true表示支持基于类生成 这样需要用到cglib false表示基于接口生成 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
注意这里
proxy-target-class="true" ,true表示支持基于类生成 这样需要用到cglib false表示基于接口生成 ,我们这里是为一个类生成代理切面 ,所以用true 。
运行
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
new String[]{"spring.xml"});
UserService userService = (UserService)applicationContext.getBean("userService");
userService.login();
}
运行结果如下

这个时候去看userService
会发现这个对象并不是我们创建的UserService对象,而是一个新的对象,这个对象是用cglib生成的 UserService的代理对象。

那么接下来分析,是在什么时候进行的生成和替换。
那么就需要debug一步步看了,这里介绍下看源码的技巧,因为很多时候新手看源码都会被绕晕。
看源码的技巧
添加链接描述
点进去之后,看到getSingleton里面返回的就是我们的要的cglib代理对象

沿着以上思路一路找下去 会发现 ,在this.singletonObjects.get(beanName) 里面取出来的时候就已经是一个代理类了。

而singletonObjects 是一个map

意味着早在get之前,代理类就已经被初始化好了并放到了map里面,用到的时候再去get。
也就是说,在Spring容器初始化之后,这个代理类的bean就已经生成了,而不是在我们真正去使用的时候才生成。
那什么时候时候生成的代理类?
全局搜this.singletonObjects.put 可以找到一段代码,在这里加上条件断点,然后启动看下

当断点进来之后,看到调用栈

可以看到,在main函数的开始,一层层的调用栈。
选择中间的位置,进去之后打上断点,重启再看下
这一步还没变化

这一步就变化了

因此
getObjectForBeanInstance(sharedInstance, name, beanName, null) 这个方法里面发生了将对象转为代理对象的变化
里面继续追踪

createBean 返回的就是代理类
一路往下看,经过n个弯之后,在DefaultAopProxyFactory里面的createAopProxy会返回具体的AopProxy ,然后调用其getProxy()方法就会返回代理对象。


流程非常长,因此省略了不少地方,主要是追踪源码的方式和要非常的耐心。
流程如下:
org.springframework.context.support.ClassPathXmlApplicationContext#ClassPathXmlApplicationContext(java.lang.String...)- 创建一个新的ClassPathXmlApplicationContext,从给定的XML文件加载bean并自动刷新上下文
org.springframework.context.support.AbstractApplicationContext#refresh- 加载或刷新容器
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization- 完成bean工厂的初始化和所有的单例bean
org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons- 确保所有非lazyinit单例都被实例化
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)- 返回一个可以共享或独立于指定bean的实例
org.springframework.beans.factory.support.AbstractBeanFactory#createBean- bean的创建
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)- 工厂回调、init方法和bean后处理器初始化给定的bean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization- 将链接BeanPostProcessor BeanPostProcessors应用到给定的现有bean实例中,调用它们的代码后置处理初始化方法。返回的bean实例可以是围绕原始的包装器。
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization- 如果子类将bean标识为一个代理,则使用配置的侦听器创建一个代理
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary- 必要时包装给定的bean(如有资格代理)
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy- 为给定的bean创建AOP代理
org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)- 根据此工厂中的设置创建新代理对象
org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy- 创建给定的AOP代理工厂实例
本文通过一个例子介绍了Spring AOP的实现过程,从创建要织入的类和切面,到配置XML,展示了如何生成并替换代理对象。在debug过程中,发现对象在Spring容器初始化后即被转换为代理类,并存放在singletonObjects map中。通过源码追踪,揭示了bean的创建、初始化、代理对象的生成等步骤,特别指出在`createAopProxy`和`getProxy()`方法中完成具体代理对象的创建。整个流程涉及多个步骤,包括bean的生命周期管理和AOP代理的生成。





