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