基于注解的面向切面的编程在使用的时候对应的代码如下:
/**
* 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就可以获取到)
网友评论