面向方面编程(AOP)补充了面向对象编程(OOP),提供了另一种思考程序结构的方式。OOP中模块化的关键单元是类,而AOP中模块化的单元是方面。 方面可以实现关注点的模块化,比如跨越多个类型和对象的事务管理。(在AOP文献中,这种关注点通常被称为横切关注点。)
简述Spring AOP实现
在之前BeanFactory及ApplicationContext的源码分析中都有提到过,Spring AOP的实现是通过实现BeanPostProcessor
接口,在前置或者后置方法中,通过返回代理对象,完成AOP的实现。这里实现一个简单的BeanPostProcessor:
public class LogInterceptor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof UserService) {
UserService us = (UserService) bean;
Object proxyInstance = Proxy.newProxyInstance(LogInterceptor.class.getClassLoader(), new Class[]{UserService.class},
(proxy, method, args) -> {
System.out.println("LogInterceptor UserService: " + method.getName() + " invoked");
return method.invoke(us, args);
});
return proxyInstance;
}
return bean;
}
}
LogInterceptor
是一个简单的日志拦截器,在bean
构建过程中,init之后,就会遍历所有的BeanPostProcessor的postProcessAfterInitialization方法,当检测到当前bean是UserService
实例时,就会返回一个代理对象,代理对象在原对象每个方法调用时都会打印一行日志,这样一个简单的日志拦截器就完成了。
运行程序
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService.getName());
System.out.println(userService.getMoney());
System.out.println(userService.getIntegral());
得到输出
LogInterceptor UserService: getName invoked
Hello World
LogInterceptor UserService: getMoney invoked
999
LogInterceptor UserService: getIntegral invoked
998
可以看到,只要实现BeanPostProcessor
,在实现接口方法类完成对想要增强bean拦截,然后完成需要的增强处理,就可以了。当然上例只是简单的接口代理,对于有些没有接口的bean,就需要CGlib完成代理了。
Spring AOP实现
当然如果每次增强操作都要这样手动处理就太麻烦了,还要考虑没有接口的类,所以Spring内部实现了AOP以简化开发。
Spring实现AOP的方式有两种,一种为ProxyFactoryBean
,对单个bean做代理;另一种为BeanPostProcessor
,根据规则,对一类bean做代理。
ProxyFactoryBean
ProxyFactoryBean是用于创建代理类的通用FactoryBean,通过配置,可以在构建bean的时候返回代理对象,而代理对象通过对 target 对象进行增强,这样在执行bean方法的时候就可以达到想要的增强后的效果。示例
spring-aop.xml 文件
<!--拦截器-->
<bean id="debugInterceptor" class="com.zero.demo.advice.DebugInterceptor"/>
<!--target-->
<bean id="mockTask" class="com.zero.demo.aop.MockTask"/>
<bean id="task" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.zero.demo.aop.ITask"/>
<property name="target" ref="mockTask"/>
<property name="interceptorNames">
<list>
<value>debugInterceptor</value>
</list>
</property>
</bean>
main方法
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader configReader = new XmlBeanDefinitionReader(beanFactory);
configReader.loadBeanDefinitions("classpath:spring-aop.xml");
ITask task = beanFactory.getBean("task", ITask.class);
task.execute();
}
可以通过调试进入beanFactory#getBean
方法,查看bean的构建,在AbstractBeanFactory#doGetBean
方法内
if (mbd.isSingleton()) {
// 构建bean,实际构建的是ProxyFactoryBean bean
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
// 根据是否是FactoryBean,构建proxy对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
对于FactoryBean,最后容器中存放的是FactoryBean#getObject
方法获得的对象,在getObjectForBeanInstance
方法内会根据 sharedInstance 是否为FactoryBean,然后决定是否调用getObject方法获取代理的对象。
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// 到这里说明一定是一个FactoryBean
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 从工厂返回bean实例。
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
getObjectFromFactoryBean
方法主要是创建bean以及创建之后的处理,创建bean的方法为doGetObjectFromFactoryBean
,这是从给定的FactoryBean获取要公开的对象的方法,核心逻辑就是factory.getObject()
,也就是ProxyFactoryBean
的getObject
方法
public Object getObject() throws BeansException {
// 创建advisor(interceptor)链。根据interceptorNames,从BeanFactory取出相应的advisor(interceptor)
initializeAdvisorChain();
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn(...);
}
return newPrototypeInstance();
}
}
先创建advisor(interceptor)链。根据interceptorNames,从BeanFactory取出相应的advisor(interceptor),然后getSingletonInstance
方法主要是调用createAopProxy
方法创建AopProxy,然后调用返回的aopProxy的getProxy方法,获取最后的proxy对象。createAopProxy
方法的调用DefaultAopProxyFactory#createAopProxy
方法,返回AopProxy对象
//DefaultAopProxyFactory#createAopProxy
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 判断使用ObjenesisCglibAopProxy还是JdkDynamicAopProxy
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException(...);
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
根据条件判断是返回ObjenesisCglibAopProxy
还是JdkDynamicAopProxy
,
// JdkDynamicAopProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
... log ..
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
newProxyInstance方法InvocationHandler参数传的是this
,也就是说,方法调用会调用自身的invoke方法
// JdkDynamicAopProxy#invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
... equal、hashCode 等等
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取此方法的拦截链。之前初始化过
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 创建一个方法调用
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(...);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
当拦截链不为空,则创建一个ReflectiveMethodInvocation,调用其proceed方法,proceed方法的调用会递归调用,直到所有的MethodInterceptor调用完
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// currentInterceptorIndex索引递增,每次调用将获取下一个MethodInterceptor
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 动态方法匹配
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// 递归调用
return proceed();
}
}
else {
// methodInterceptor传参为this,只要methodInterceptor内调用proceed方法,将递归调用
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
这样Spring AOP拦截链就调用完毕。
BeanPostProcessor
Spring更为常见的AOP使用是BeanPostProcessor
,使用BeanPostProcessor
可以通过名称或者正则表达式,更加便捷的对一类bean进行AOP操作。下面是简单xml配置
<bean id="debugInterceptor" class="com.zero.demo.advice.DebugInterceptor"/>
<bean id="logInterceptor" class="com.zero.demo.advice.LogInterceptor"/>
<bean id="task" class="com.zero.demo.aop.MockTask"/>
<bean id="processor" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="task,*Service,*Dao"/>
<property name="interceptorNames">
<list>
<value>debugInterceptor</value>
<value>logInterceptor</value>
</list>
</property>
</bean>
示例是使用BeanNameAutoProxyCreator
,根据名称自动匹配,名称可以用通配符。main函数如下
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader configReader = new XmlBeanDefinitionReader(beanFactory);
configReader.loadBeanDefinitions("classpath:spring-aop.xml");
// 因为使用的是beanFactory,所以需要手动注册BeanPostProcessor,ApplicationContex会自动注册
BeanPostProcessor processor = beanFactory.getBean("processor", BeanPostProcessor.class);
beanFactory.addBeanPostProcessor(processor);
ITask task = beanFactory.getBean("mockTask", ITask.class);
task.execute();
}
这里使用的BeanPostProcessor是BeanNameAutoProxyCreator
,BeanNameAutoProxyCreator
实现了SmartInstantiationAwareBeanPostProcessor
接口
SmartInstantiationAwareBeanPostProcessor
的继承关系及方法
SmartInstantiationAwareBeanPostProcessor
及继承的接口都会影响bean的构建,所以实际上只要看看BeanNameAutoProxyCreator
对SmartInstantiationAwareBeanPostProcessor
接口的实现即可。
其中,直接可以返回代理bean的方法有
- postProcessBeforeInstantiation,在bean构建开始之前拦截
- postProcessBeforeInitialization,在bean init之前拦截
- postProcessAfterInitialization,在bean init之后拦截
其他的方法主要是bean的类型,构造函数以及属性注入等。
postProcessBeforeInstantiation
方法
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 如果我们有一个定制的TargetSource,在这里创建代理。
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 创建proxy
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
也就是xml文件中配置了customTargetSourceCreators
属性,则会在bean的构建之前拦截。createProxy
是核心创建代理的方法,后面详细分析。
postProcessBeforeInitialization
方法直接返回传入的bean,无其他逻辑
postProcessAfterInitialization
方法
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
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;
}
// 如果有advice,创建代理。
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;
}
postProcessAfterInitialization
方法如果有advice,则创建代理,创建代理的逻辑和postProcessBeforeInstantiation
方法类似,下面重点看一下createProxy
方法
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
可以看到核心逻辑有3处
- 创建ProxyFactory:ProxyFactory proxyFactory = new ProxyFactory();
- 获得advisors:Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
- 构建代理:return proxyFactory.getProxy(getProxyClassLoader());
ProxyFactory
的getProxy
方法其实和前面介绍的ProxyFactoryBean
类似,ProxyFactory
和ProxyFactoryBean
共同继承ProxyCreatorSupport
,实现代理的逻辑都来自于超类ProxyCreatorSupport
。
Spring 事务
稍带提一句,Spring 事物的拦截处理主要由TransactionInterceptor
实现。
网友评论