Spring之AOP代理对象的产生(一)

本文深入探讨Spring中AOP代理对象的产生过程,从源码层面解析单例bean的创建,关注于代理对象如何在bean实例化和属性填充后生成。详细阐述了从初始化到最终完成代理对象创建的步骤,包括三级缓存、接口初始化等关键环节。
摘要由CSDN通过智能技术生成

1. 准备

1.1. 接口

public interface UserService {
   
    String query();
}

1.2. 接口的实现

@Service
public class UserServiceImpl implements UserService {
   

    @Override
    public String query() {
   
        System.out.println("------------ yz ------------");
        return "yz";
    }
}

1.3. 切面类

@Aspect
@Component
public class AopConfig {
   

    @Pointcut(value = "execution(* com.atguigu.springIOC.UserServiceImpl.*(..))")
    public void businessService() {
   
    }

    @Before(value = "businessService()")
    public void doBefore() {
   
        System.out.println("----------------- doBefore -----------------");
    }

    @AfterReturning(value = "businessService()")
    public void doAfterReturning() {
   
        System.out.println("----------------- doAfterReturning -----------------");
    }

    @After(value = "businessService()")
    public void doAfter() {
   
        System.out.println("----------------- doAfter -----------------");
    }
}

1.4. 测试类

// 该注解在测试时必须添加;在使用 springboot 较高版本启动运行程序时,可以不添加
@EnableAspectJAutoProxy
@ComponentScan(basePackages = {
   "com.atguigu.springIOC"})
public class BeanTest {
   

    public static void main(String[] args) {
   
        // 获取 spring IOC 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest.class);
        // 从容器中获取 bean
        UserService userService = (UserService) applicationContext.getBean("userServiceImpl");
        String query = userService.query();
        System.out.println(query);
    }
}

1.5. 测试结果

----------------- doBefore -----------------
------------ yz ------------
----------------- doAfter -----------------
----------------- doAfterReturning -----------------
yz

2. Spring AOP 代理对象的产生

2.1. 源码解读之前

既然要产生代理对象,我们进行源码分析,无非就是从下面两行代码入手

// 获取 spring IOC 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest.class);
// 从容器中获取 bean
UserService userService = (UserService) applicationContext.getBean("userServiceImpl");

通过 spring 初始化 bean(单例) 过程 的文章分析,userServiceImpl 这个 bean 会通过 getBean() 从一级缓存 singletonObjects 中能获取到。那么 userServiceImpl 的代理对象肯定从下面的代码中产生

// 获取 spring IOC 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest.class);

2.2. 抽象类 AbstractBeanFactorydoGetBean()

关于代码

// 获取 spring IOC 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest.class);

的过程,鉴于篇幅本篇文章不再详细赘述,详细过程请查看,我们从这个 doGetBean 方法开始

@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
		@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
   

    // 通过 name 获取 beanName。这里不使用 name 直接作为 beanName 有两个原因
	// 1、name 可能会以 & 字符开头,表明调用者想获取 FactoryBean 本身,而非 FactoryBean
	//   实现类所创建的 bean。在 BeanFactory 中,FactoryBean 的实现类和其他的 bean 存储
	//   方式是一致的,即 <beanName, bean>,beanName 中是没有 & 这个字符的。所以我们需要
	//   将 name 的首字符 & 移除,这样才能从缓存里取到 FactoryBean 实例。
	// 2、还是别名的问题,转换需要 &beanName
	final String beanName = transformedBeanName(name);
	Object bean;

	// 先从缓存中获取,因为在容器初始化的时候或者其他地方调用过getBean,已经完成了初始化
	Object sharedInstance = getSingleton(beanName);
	if (sharedInstance != null && args == null) {
   
		if (logger.isDebugEnabled(
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值