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

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

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






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值