1. spring aop案例(POJO注入)
1.0 被代理接口 TargetInterface
/**
* 被代理的接口
* @author Yang ZhiWei
*/
public interface TargetInterface {
void show();
String showName();
}
1.1 被代理对象
@Slf4j
public class TargetObject implements TargetInterface {
@Override
public void show() {
log.info("show----->I am a TargetObject!");
}
@Override
public String showName() {
return "showName--->TargetObject !";
}
}
1.2 通知 MyAdvice
@Slf4j
public class MyAdvice {
public void takeSeat() {
log.info("====> MethodBeforeAdvice:Take Seat!");
}
public void turnOffPhone() {
log.info("==> MethodBeforeAdvice:turn Off Phone!");
}
public void applaud(Object res) { //xml配置返回值
log.info("==> AfterReturning:applaud,returning=" + res);
}
public void demandRefund(Exception e) {
log.info("==> AfterThrowing:demandRefund,Exception=" + e);
}
public void goHone() {
log.info("After:go Home!");
}
}
1.3 AOP配置 applicationContext-pojo.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd ">
<!-- 配置目标对象 -->
<bean id="targetObject" class="com.zhiwei.aop.pojo.TargetObject"/>
<!-- 配置切面 -->
<bean id="myAdvice" class="com.zhiwei.aop.pojo.MyAdvice"/>
<!-- 通过配置xml将pojo暴露成切面 -->
<aop:config>
<!-- 配置切面, ref 配置切面关联的通知 -->
<aop:aspect ref="myAdvice">
<!-- 定义切点 -->
<aop:pointcut id="definePointCut"
expression="execution(* com.zhiwei.aop.pojo.TargetInterface.showName(..)) and
within(com.zhiwei.aop.pojo.*)" />
<!-- 通知织入切入点及关联通知 -->
<aop:before method="takeSeat" pointcut-ref="definePointCut"/>
<aop:before method="turnOffPhone" pointcut-ref="definePointCut"/>
<aop:after-returning method="applaud" pointcut-ref="definePointCut" returning="res"/>
<aop:after-throwing method="demandRefund" pointcut-ref="definePointCut" throwing="e"/>
<aop:after method="goHone" pointcut-ref="definePointCut"/>
</aop:aspect>
</aop:config>
</beans>
1.4 测试效果
public class TestPojo {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-pojo.xml");
TargetInterface targetInterface = applicationContext.getBean(TargetInterface.class);
targetInterface.showName();
targetInterface.show();
}
}
日志:
INFO [main] - MyAdvice - ====> MethodBeforeAdvice:Take Seat!
INFO [main] - MyAdvice - ==> MethodBeforeAdvice:turn Off Phone!
INFO [main] - MyAdvice - ==> AfterReturning:applaud,returning=showName--->TargetObject !
INFO [main] - MyAdvice - After:go Home!
INFO [main] - TargetObject - show----->I am a TargetObject!
2. AOP代理对象生成逻辑
2.1 aop:config 解析
spring 标签解析器配置:META-INF/spring.handlers
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
分析:XML命名空间解析器:AopNamespaceHandler
AopNamespaceHandler:aop 命名空间解析器
public class AopNamespaceHandler extends NamespaceHandlerSupport {
/**
* Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
* '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
* and '{@code scoped-proxy}' tags.
*/
@Override
public void init() {
// 主要关主aop:config 解析,主要注册AspectJAwareAdvisorAutoProxyCreator,用于创建代理对象
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
ConfigBeanDefinitionParser: aop:config解析器
解析接口:org.springframework.aop.config.ConfigBeanDefinitionParser.parse
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
// 配置代理对象自动创建器
configureAutoProxyCreator(parserContext, element);
List<Element> childElts = DomUtils.getChildElements(element);
for (Element elt: childElts) {
String localName = parserContext.getDelegate().getLocalName(elt);
if (POINTCUT.equals(localName)) {
parsePointcut(elt, parserContext);
}
else if (ADVISOR.equals(localName)) {
parseAdvisor(elt, parserContext);
}
else if (ASPECT.equals(localName)) {
parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
configureAutoProxyCreator(parserContext, element); 调用栈
org.springframework.aop.config.ConfigBeanDefinitionParser.configureAutoProxyCreator
org.springframework.aop.config.AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary
org.springframework.aop.config.AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary
@Nullable
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 注入AspectJAwareAdvisorAutoProxyCreator Bean
return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}
aop:config: 主要作用就是注入AspectJAwareAdvisorAutoProxyCreator,用于后续创建代理对象
2.2 BeanPostProcessor(预备知识)
作用:Bean后置处理器,在Bean属性封装完成后,在对Bean进行额外操作,Spring AOP代理对象也是在此声明周期间完成代理对象创建工作
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;
}
}
方法在Bean声明周期执行顺序如下(忽略其他细节):
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean -->
BeanPostProcessor.postProcessBeforeInitialization -->
org.springframework.beans.factory.InitializingBean.afterPropertiesSet --》
Bean.init-method(bean自定义初始化方法) -->
BeanPostProcessor.postProcessAfterInitialization -->
生成Bean实例放入IOC容器,最终放入一级缓存(singletonObjects)
调用链:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean
Bean初始化:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 包含Bean生命周期接口
// BeanNameAware: 获取Bean注册IOC容器标识
// BeanClassLoaderAware: 获取Bean类加载器
// BeanFactoryAware: 获取Bean工厂
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 重点:BeanPostProcessor 完成实例化前置处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 声明周期接口
// InitializingBean: Bean属性封装完成后执行接口
// init-method: 对象初始化初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 重点:BeanPostProcessor 完成实例化前置处理,代理对象生成是最后处理步骤,因此代理对象生成逻辑一般在后置处理逻辑
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
2.3 AspectJAwareAdvisorAutoProxyCreator 后置处理器
源码:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// IOC容器默认配置多个BeanPostProcessor,多个处理器顺序处理,这里只关注前面aop:config注入的AspectJAwareAdvisorAutoProxyCreator
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
父类:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization
@Override
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;
}
// XML配置多种通知,这里根据AOP切点去匹配Bean是否属于拦截范围,若属于则返回有效拦截通知:After、AfterThrowing、AfterReturning、Before
// 注意:通知拦截包含对象ExposeInvocationInterceptor,主要是用于调用代理对象方法时再调用各种通知处理,类似AQS的等待队列,1个通知处理完自动唤醒下1个通知处理
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;
}
创建AOP代理对象:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 暴露目标类:这里主要时维护代理对象的基础类,放到BeanDefinition维护(属性名:AutoProxyUtils.originalTargetClass)
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//构建代理类工厂
ProxyFactory proxyFactory = new ProxyFactory();
// 复制AOP配置
proxyFactory.copyFrom(this);
// 判断是否是类代理,spring AOP默认接口代理
if (!proxyFactory.isProxyTargetClass()) {
// 进一步判断是否应该类代理,若是则设置类代理标识true
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
//评估代理接口,剔除回调、Groovy、cglib等无用接口,并将最终被代理的接口维护到proxyFactory
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 将通知转换为Advisor,里面包含通知信息
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
// 设置被带离对象源
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 创建AOP代理对象,并返回最终的代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
2.4 创建代理对象:DefaultAopProxyFactory#createAopProxy
接口:org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// AOP Proxy优化、类代理、没有被代理的合理接口 (例如:DisposableBean、Groovy、Cglib等无用接口)
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 如果是接口代理或接口是Proxy的继承接口,则JDK动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// Cglib 类代理
return new ObjenesisCglibAopProxy(config);
}
else {
// 默认JDK动态代理
return new JdkDynamicAopProxy(config);
}
}
JdkDynamicAopProxy
实现接口:AopProxy(AOP代理对象获取接口)、InvocationHandler(JDK动态代理类处理逻辑接口)
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// JDK动态代理对象生成,这里InvocationHandler为this,说白了最后代理对象又转回JdkDynamicAopProxy
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
回到 return proxyFactory.getProxy(getProxyClassLoader()); 定位到 org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(java.lang.ClassLoader), 最终Spring AOP将JdkDynamicAopProxy作为代理对象返回最终到IOC容器, 至此整个Spring AOP代理对象创建完成,以后引用该对象即引用其代理对象
来源:oschina
链接:https://my.oschina.net/yangzhiwei256/blog/4396343