【Spring】AOP的代理默认是Jdk还是Cglib?
2021-05-07 10:29
标签:creation 完成 rest 现在 com orb 创建 调用 util 菜瓜:你觉得AOP是啥 水稻:我觉得吧,AOP是对OOP的补充。通常情况下,OOP代码专注功能的实现,所谓面向切面编程,大多数时候是对某一类对象的方法或者功能进行增强或者抽象 菜瓜:我看你这个理解就挺抽象的 水稻:举个栗子??!我要在满足开闭原则的基础下对已有功能进行扩展 菜瓜:你说的这个low一点的方法怎么好像是在说我??? 水稻:建议看一下动态代理设计模式【DP-动态代理】JDK&Cglib,我当然知道你不会看,所以我还准备了自定义注解的栗子 菜瓜:这个自定义注解又是怎么实现的呢? 水稻:不愧是你,没有源码看来是满足不了你的好奇心了!!不知道你是否还记得我们之前有聊到过bean创建完毕后会调用一些PostProcessor对其进一步操作 菜瓜:有印象,@PostConstruct注解就是InitDestroyAnnotationBeanPostProcessor在这里调用的,还自定义过BeanPostProcessorT对象打印输出过bean信息 水稻:你猜Spring是怎么操作的 菜瓜:let me try try。结合刚刚的栗子和提示,大胆猜测应该是用PostProcessor在bean创建完成之后生成代理对象。实际调用代理的invoke方法实现对被代理bean的增强 水稻:思路正确。看脉络 菜瓜:然后代理类中都有invoke方法,那些advice(@Around,@Before...)在invoke中找到适当时机调用对吧 水稻:是的,这里我想结合@Transactional注解会更容易理解,你肯定用过这个注解吧,它其实。。。 菜瓜:停。。。今天获取的知识量已经够了,我下去自己断点走一趟再熟悉熟悉。下次请结合Transactional注解再敲打我吧 水稻:也好,我下去再给你准备几个栗子?? 总结: 【Spring】AOP的代理默认是Jdk还是Cglib? 标签:creation 完成 rest 现在 com orb 创建 调用 util 原文地址:https://www.cnblogs.com/nightOfStreet/p/13185406.html
package com.hb.merchant.config.aop;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* @author QuCheng on 2020/6/23.
*/
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
}
package com.hb.merchant.config.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author QuCheng on 2020/6/23.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OperatorLog {
}
package com.hb.merchant.config.aop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
/**
*
* @author QuCheng on 2020/6/23.
*/
@Aspect
@Component
@Slf4j
public class OperatorAspect {
@Around("@annotation(OperatorLog)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
//获取要执行的方法
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//记录方法执行前日志
log.info("startLog: {} 开始了。。。" , methodSignature.getName());
//获取方法信息
String[] argNames = methodSignature.getParameterNames();
// 参数值:
final Object[] argValues = joinPoint.getArgs();
StringBuilder sb = new StringBuilder();
for (int i = 0; i ) {
String value = argValues[i] == null ? "null" : argValues[i].toString();
sb.append(argNames[i]).append("=").append(value).append(",");
}
String paramStr = sb.length() > 0 ? sb.toString().substring(0, sb.length() - 1) + "]" : "";
log.info("参数信息为:[{}", paramStr);
//执行方法
Object result;
try {
result = joinPoint.proceed();
} catch (Exception e) {
log.error("errorLog", e);
return null;
}
//记录方法执行后日志
log.info("endLog: {} 结束了。。。" , methodSignature.getName());
return result;
}
}
package com.hb.merchant.controller.icbc.item.oc;
import com.hb.merchant.config.aop.OperatorLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author QuCheng on 2020-06-23.
*/
@RestController
@RequestMapping("/item")
@Slf4j
public class ItemOcController {
@OperatorLog
@GetMapping("/delete")
public String delete(Long itemId) {
Assert.notNull(itemId,"itemId不能为空");
return "delete finished ...";
}
}
// 后台打印
startLog: delete 开始了。。。
参数信息为:[itemId=1]
endLog: delete 结束了。。。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
。。。
// BeanNameAware BeanFactoryAware ...
invokeAwareMethods(beanName, bean);
。。。
// BeanPostProcessorBefore @PostConstruct
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
。。。
// initMethod InitializingBean接口
invokeInitMethods(beanName, wrappedBean, mbd);
。。。
if (mbd == null || !mbd.isSynthetic()) {
// aop
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
。。。
// 收集切面信息匹配被代理对象
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;
}
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
// jdk动态代理类
return new JdkDynamicAopProxy(config);
}
// cglib
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
上一篇:c++运算符重载
文章标题:【Spring】AOP的代理默认是Jdk还是Cglib?
文章链接:http://soscw.com/index.php/essay/83639.html