Spring AOP代理对象创建时机

1、AOP代理对象创建的时机

public class 代理对象 {

    private 普通对象类型 普通对象;

    
    public Object proxyMethod(...) {
        
        do something
        普通对象.method(xxx)
        do something
    }
} 

AOP的原理可以简单这么认为,代理对象持有被代理对象(因为代理对象的字段并不会被赋值,都是null,所以需要用到被代理对象字段的值),通过在调用被代理对象方法前后做一些事情。

在Spring中,我们经常会为我们的Bean做AOP,根据上面我们知道,代理对象需要引用被代理对象,那就需要在Bean初始化完成之后再对Bean做代理。因为Bean初始化完成之后就是一个可用的Bean了,而且会被放入IOC容器,我们需要在这个Bean被放入IOC容器之前生成它的代理对象,并代替原先的类放入IOC容器中。

 这是一个Bean的生命周期流程,当它执行完第六步,也就是初始化方法执行完毕之后,这个Bean就可用了。而第七步是Spring给我们提供的扩展点,在这一步可以拿到可用的原始对象,我们的代理对象生成和替换就是在这里。

public interface BeanPostProcessor {


	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}


	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

位置:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

 位置:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

 从源码可以知道,Spring在调用BeanPostProcessor的postProcessAfterInitialization方法会传入原始对象,并把postProcessAfterInitialization方法返回的对象替换原始对象,所以我们只要在postProcessAfterInitialization方法实现代理对象的生成逻辑即可。

2、实现

我用的是JDK动态代理,所以需要被代理的对象去实现一个接口。

public interface TestInterface {

    void test();

}

然后被代理类通过依赖注入注入另一个类,去调用该类的一个方法。验证被代理类被代理前已经可用。

@Service
public class OtherTestService {

    public void test() {
        System.out.println("OtherTestService test()");
    }

}

被代理类

@Service
public class TestImpl implements TestInterface {

    @Autowired
    private OtherTestService otherTestService;

    @Override
    public void test() {
        otherTestService.test();
    }
}

生成代理类



@Component
public class TestBeanPostProcess implements BeanPostProcessor {

    public Object postProcessAfterInitialization(Object bean, String beanName) throws
            BeansException {

        // 只代理testImpl这个bean 其他的不代理
        if (!beanName.equals("testImpl")) {
             return bean;
        }

        return Proxy.newProxyInstance(TestBeanPostProcess.class.getClassLoader(),
                bean.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                        System.out.println("代理前");
                        Object invoke = method.invoke(bean, args);
                        System.out.println("代理后");
                        return invoke;
                    }
                });
    }
}

3、Test

@SpringBootApplication
public class AopDemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(AopDemoApplication.class, args);
        TestInterface testImpl = (TestInterface) run.getBean("testImpl");
        testImpl.test();
    }

}

demo 代码:https://download.csdn.net/download/qq_41084438/87620267

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值