spring的AOP基于JDK的动态代理和cglib实现,默认代理对象是某个接口的实现就会使用JDK动态代理,否则使用cglib,使用cglib时要注意,代理类不能是final类型,否则无法进行代理
AOP示例
@Aspect
@Component
public class SystemLogAspect {
//注入Service用于把日志保存数据库
@Resource
private SystemLogService systemLogService;
private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);
//Controller层切点
@Pointcut("execution (* com.gcx.controller..*.*(..))")
public void controllerAspect() {
}
/**
* 前置通知 用于拦截Controller层记录用户的操作
*
* @param joinPoint 切点
*/
@Before("controllerAspect()")
public void doBefore(JoinPoint joinPoint) {
System.out.println("==========执行controller前置通知===============");
if(logger.isInfoEnabled()){
logger.info("before " + joinPoint);
}
}
//配置controller环绕通知,使用在方法aspect()上注册的切入点
@Around("controllerAspect()")
public void around(JoinPoint joinPoint){
System.out.println("==========开始执行controller环绕通知===============");
long start = System.currentTimeMillis();
try {
((ProceedingJoinPoint) joinPoint).proceed();
long end = System.currentTimeMillis();
if(logger.isInfoEnabled()){
logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");
}
System.out.println("==========结束执行controller环绕通知===============");
} catch (Throwable e) {
long end = System.currentTimeMillis();
if(logger.isInfoEnabled()){
logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());
}
}
}
/**
* 后置通知 用于拦截Controller层记录用户的操作
*
* @param joinPoint 切点
*/
@After("controllerAspect()")
public void after(JoinPoint joinPoint) {
User user = new User();
user.setId(1);
user.setName("张三");
String ip = "127.0.0.1";
try {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String operationType = "";
String operationName = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
operationType = method.getAnnotation(Log.class).operationType();
operationName = method.getAnnotation(Log.class).operationName();
break;
}
}
}
//*========控制台输出=========*//
System.out.println("=====controller后置通知开始=====");
System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);
System.out.println("方法描述:" + operationName);
System.out.println("请求人:" + user.getName());
System.out.println("请求IP:" + ip);
//*========数据库日志=========*//
SystemLog log = new SystemLog();
log.setId(UUID.randomUUID().toString());
log.setDescription(operationName);
log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);
log.setLogType((long)0);
log.setRequestIp(ip);
log.setExceptioncode( null);
log.setExceptionDetail( null);
log.setParams( null);
log.setCreateBy(user.getName());
log.setCreateDate(new Date());
//保存数据库
systemLogService.insert(log);
System.out.println("=====controller后置通知结束=====");
} catch (Exception e) {
//记录本地异常日志
logger.error("==后置通知异常==");
logger.error("异常信息:{}", e.getMessage());
}
}
//配置后置返回通知,使用在方法aspect()上注册的切入点
@AfterReturning("controllerAspect()")
public void afterReturn(JoinPoint joinPoint){
System.out.println("=====执行controller后置返回通知=====");
if(logger.isInfoEnabled()){
logger.info("afterReturn " + joinPoint);
}
}
/**
* 异常通知 用于拦截记录异常日志
*
* @param joinPoint
* @param e
*/
@AfterThrowing(pointcut = "controllerAspect()", throwing="e")
public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
//获取用户请求方法的参数并序列化为JSON格式字符串
User user = new User();
user.setId(1);
user.setName("张三");
String ip = "127.0.0.1";
String params = "";
if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
for ( int i = 0; i < joinPoint.getArgs().length; i++) {
params += JsonUtil.getJsonStr(joinPoint.getArgs()[i]) + ";";
}
}
try {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String operationType = "";
String operationName = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
operationType = method.getAnnotation(Log.class).operationType();
operationName = method.getAnnotation(Log.class).operationName();
break;
}
}
}
/*========控制台输出=========*/
System.out.println("=====异常通知开始=====");
System.out.println("异常代码:" + e.getClass().getName());
System.out.println("异常信息:" + e.getMessage());
System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);
System.out.println("方法描述:" + operationName);
System.out.println("请求人:" + user.getName());
System.out.println("请求IP:" + ip);
System.out.println("请求参数:" + params);
/*==========数据库日志=========*/
SystemLog log = new SystemLog();
log.setId(UUID.randomUUID().toString());
log.setDescription(operationName);
log.setExceptioncode(e.getClass().getName());
log.setLogType((long)1);
log.setExceptionDetail(e.getMessage());
log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
log.setParams(params);
log.setCreateBy(user.getName());
log.setCreateDate(new Date());
log.setRequestIp(ip);
//保存数据库
systemLogService.insert(log);
System.out.println("=====异常通知结束=====");
} catch (Exception ex) {
//记录本地异常日志
logger.error("==异常通知异常==");
logger.error("异常信息:{}", ex.getMessage());
}
/*==========记录本地异常日志==========*/
logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);
}
}
@Aspect就是所谓的切面也叫做Advisor的织入,@Pointcut就是切点
AOP源码分析
涉及到几个关键的类AspectJAutoProxyBeanDefinitionParser,AnnotationAwareAspectJAutoProxyCreator,AbstractAutoProxyCreator,BeanPostProcessor。其中AnnotationAwareAspectJAutoProxyCreator是AOP的核心,AspectJAutoProxyBeanDefinitionParser主要是对AnnotationAwareAspectJAutoProxyCreator完成注册,AnnotationAwareAspectJAutoProxyCreator负责将获取到的aop的bean解析成出各种属性信息最后生成代理
- AspectJAutoProxyBeanDefinitionParser的parse方法中调用registerAspectJAnnotationAutoProxyCreatorIfNecessary来向容器注册AnnotationAwareAspectJAutoProxyCreator,其中传入的element参数携带了AOP的xml节点资源,用于后面spring加载AnnotationAwareAspectJAutoProxyCreator生成代理代理使用
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
//AopNamespaceUtils类的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
//AopConfigUtils类的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
//cls就是AnnotationAwareAspectJAutoProxyCreator.class,将和element节点资源一起封装为beanDefinition 注册入容器中
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//注册到容器内
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
接下来是解析AnnotationAwareAspectJAutoProxyCreator创建AOP的过程
先看看AnnotationAwareAspectJAutoProxyCreator的继承图AnnotationAwareAspectJAutoProxyCreator继承了BeanPostProcessor,AOP的创建是在spring加载AnnotationAwareAspectJAutoProxyCreator这个bean的时候,在这个bean实例化后调用其父类BeanPostProcessor的postProcessAfterInitialization方法,这个方法已经由父类AbstractAutoProxyCreator实现了
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
AnnotationAwareAspectJAutoProxyCreator可以根据@Pointcut自动代理匹配的bean。AnnotationAwareAspectJAutoProxyCreator是实现了BeanPostProcessor,当spring初实例化完这个bean后会调用后置处理器的后置处理方法postProcessAfterInitialization,这个方法是其实是调用的AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator中的实现,其中关键的方法是wrapIfNecessary,wrapIfNecessary主要是获取切面的增强方法,加载标注有aop注解的bean,并将这些bean的增强方法包装成Advisor,Advisor中包装了增强方法的各类信息、增强器和注解上信息和通配符等,例如:" @AfterReturning("controllerAspect()")、execution (* com.gcx.controller...(..))",根据注解生成和初始化增强器,每一个增强方法都会包装成一个Advisor,然后调用createProxy方法根据注解的通配符信息创建生成相应的代理,根据bean的类型选择jdk的动态代理还GCLIB
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;
}
// 获取切面所有的增强方法,并将其相关信息封装为Advisor类
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;
}
AbstractAdvisorAutoProxyCreator类的getAdvicesAndAdvisorsForBean方法主要是获取aop注解的bean的增强方法,生成Advisor包装类,包装增强器和AOP注解上的通配符信息等
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//查找aop的注解的bean,获取增强方法的消息,封装成Advisor
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
查找aop的注解的bean,获取增强方法的消息,封装成Advisor,主要的过程就是从容器中获取所有的beanName,然后遍历,将有aop注解的类提取出来进行处理,然后获取这些bean的增强方法信息,然后将其封装到Advisor中
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
public List<Advisor> findAdvisorBeans() {
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
..........................
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
...........................
}
}
}
return advisors;
}
获取切面所有的增强方法,并将其相关信息封装为Advisor类后调用AbstractAutoProxyCreator类的createProxy方法,使用proxyFactory.getProxy创建代理。对于代理类的创建及处理,spring将其委托给了ProxyFactory,buildAdvisors方法将前面封装的一大堆Advisor进一步封装成config参数并加入ProxyFactory中同时将拦截器一并封装为Advisor也加入到ProxyFactory中,这些Advisor作为创建代理的信息依据
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 (Proxy.isProxyClass(beanClass)) {
for (Class<?> ifc : beanClass.getInterfaces()) {
proxyFactory.addInterface(ifc);
}
}
}
else {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//将所有封装好的advisors 置入ProxyFactory中
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
return proxyFactory.getProxy(classLoader);
}
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
在DefaultAopProxyFactory类中判断需要代理的bean是否有接口,有接口的则使用jdk的动态代理,否则使用cglib创建代理,创建代理是根据之前封装的消息进行创建的
//在DefaultAopProxyFactory类中判断需要代理的bean是否有接口,有接口的则使用jdk的动态代理,否则使用cglib创建代理
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(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)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}
by the way
在上次分析的IOC中说到bean存入三级缓存会调用一个匿名函数,这个匿名函数也是AbstractAutoProxyCreator类的,会触发wrapIfNecessary方法,也会产生代理
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
网友评论