基於註解的面向切面的編程在使用的時候對應的代碼如下:
/**
* AsyncLoadHandlerAop.java
* author: yujiakui
* 2018年4月17日
* 下午6:44:08
*/
package com.alibaba.asyncload.impl.annotation;
import java.text.MessageFormat;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import com.alibaba.asyncload.impl.util.MethodFilterUtil;
/**
* @author yujiakui
*
* 下午6:44:08
*
* 異步加載處理aop
*
*/
// 使用cglib代理生成目標類,如果不指定則默認是jdk proxy方式,注意兩者的區別
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Component
@Aspect
public class AsyncLoadHandlerAop {
/** logger */
private static final Logger LOGGER = LoggerFactory.getLogger(AsyncLoadHandlerAop.class);
/** 異步加載處理工廠類 */
@Autowired
private AsyncLoadHandleFactory asyncLoadHandleFactory;
@Pointcut("@within(com.alibaba.asyncload.impl.annotation.AsyncClass)")
public void aspectjMethod() {
}
/**
* Around 手動控制調用核心業務邏輯,以及調用前和調用後的處理,
*
* @param pjp
* @return
* @throws Throwable
*/
@Around(value = "aspectjMethod()")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
LOGGER.info("coming-------------");
// 對方法進行過濾
if (MethodFilterUtil.filterMethod(pjp)) {
return pjp.proceed();
} else {
LOGGER.info(MessageFormat.format("異步並行框架處理開始pjp={0}", pjp.toShortString()));
return asyncLoadHandleFactory.handle(pjp);
}
}
}
對應的註解AsyncClass代碼如下:
/**
* AsyncClass.java
* author: yujiakui
* 2018年4月17日
* 下午3:06:31
*/
package com.alibaba.asyncload.impl.annotation;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(RUNTIME)
@Target({ TYPE })
@Inherited
/**
* @author yujiakui
*
* 下午3:06:31
*
*/
public @interface AsyncClass {
/**
* 異步方法列表
*
* @return
*/
AsyncMethod[] asyncMethods() default {};
/**
* 類級別線程池配置
*
* @return
*/
AsyncThreadPoolConfig classThreadPoolConf() default @AsyncThreadPoolConfig;
}
對應的項目pom.xml配置要增加如下內容:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
測試代碼如下:
/**
* AsyncLoadAnnotationTest.java
* author: yujiakui
* 2018年4月18日
* 下午3:25:33
*/
package com.alibaba.asyncload.annotation;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.alibaba.asyncload.domain.AsyncLoadTestModel;
import junit.framework.Assert;
/**
* @author yujiakui
*
* 下午3:25:33
*
*/
public class AsyncLoadAnnotationTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
"com.alibaba.asyncload.impl.annotation", "com.alibaba.asyncload.annotation",
"com.alibaba.asyncload.domain");
System.out.println(annotationConfigApplicationContext.getBeanDefinitionNames());
// 執行測試
AsyncLoadAnnotationTestServiceImpl service = annotationConfigApplicationContext
.getBean(AsyncLoadAnnotationTestServiceImpl.class);
}
}
(1) 如果AsyncLoadAnnotationTestServiceImpl 實現的有對應的接口且在切面中沒有指定proxyTargetClass,則在spring 容器中AsyncLoadAnnotationTestServiceImpl 對應的bean是使用jdk proxy實現的,此時運行這行代碼就會報錯:
AsyncLoadAnnotationTestServiceImpl service = annotationConfigApplicationContext
.getBean(AsyncLoadAnnotationTestServiceImpl.class);
異常信息如下:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.alibaba.asyncload.annotation.AsyncLoadAnnotationTestServiceImpl' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:353)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1090)
at com.alibaba.asyncload.annotation.AsyncLoadAnnotationTest.main(AsyncLoadAnnotationTest.java:33)
(2) 如果AsyncLoadAnnotationTestServiceImpl沒有實現接口,且不需要在切面中指定proxyTargetClass=true,也是使用cglib進行代理
(3)如果指定@EnableAspectJAutoProxy(proxyTargetClass = true) 則不管什麼情況都是cglib進行代理。
cglib代理和jdk proxy代理的區別如下:
cglib代理是直接生產對應的類的子類,所以你使用getbean方法可以獲得,而jdk的proxy使用是代理模式(和目標類實現同一個接口,所以你使用目標類型進行getbean肯定是得不到的,但是如果使用接口類型進行getbean就可以獲取到)