美文网首页
基于注解的面向切面编程aspect注意点

基于注解的面向切面编程aspect注意点

作者: 瑜骐 | 来源:发表于2018-04-18 18:28 被阅读0次

基于注解的面向切面的编程在使用的时候对应的代码如下:

  /**
 * 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就可以获取到)

相关文章

网友评论

      本文标题:基于注解的面向切面编程aspect注意点

      本文链接:https://www.haomeiwen.com/subject/qjrbkftx.html