AOP中获得自定义注解对象

1.自定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 横切逻辑注解
 * @author xdc
 */
@Target({ElementType.METHOD}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface Operation{

	OperType type();
}

说明:必须使用@Retention(RetentionPolicy.RUNTIME) 进行声明,否则系统启动异常。


2.注解使用

@Operation(type=OperType.DELETE)
@Override
public void deleteProject(String id) {
		
	// 代码逻辑...
		
}


说明:service层接口实现类中的某个方法。


3.需要用的的枚举类

/**
 * 操作类型
 * @author xdc
 */
public enum OperType {

	SAVE("新建"), UPDATE("更新"), DELETE("删除");
	
	private String type;
	
	private OperType(String type){
		this.type = type;
	}
	
	public String toString(){
		return type;
	}
}


4.AOP中使用

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ProjectAspect {
	
	@Before("@annotation(oper)")
	public void test(JoinPoint joinPoint, Operation oper) throws Exception {
		System.out.println(oper.type());
	}
}

说明:@before中@annotation注解里面的值必须和下面方法里的参数对应,否则启动报错。



另一项目使用记录

1.注解

@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface SyncEs {

    //需要的查询条件
    String[] conditions() default {};

    //查询条件对应的查询字段
    String[] conditionKeys() default {};

    //需要同步的es数据表
    Class<?> esIndexClass() default ESAssetCardInfo.class;

    //直接指定id同步
    String indexId() default "0";

    /**
     * 查询条件是 and /  or
     * @return
     */
    EsLogical esLogical() default EsLogical.AND;

}

2.枚举类

public enum EsLogical {
    AND, OR
}

3.环绕增强

@Component
@Aspect
public class SyncEsAspect {

    private static final Logger Log = LoggerFactory.getLogger(SyncEsAspect.class);

    @Resource(name = "esCardRepository")
    private EsCardRepository esCardRepository;

    @Resource(name = "assetCardSearchService")
    private AssetCardSearchService assetCardSearchService;

    private static final ExpressionParser expressionParser = new SpelExpressionParser();
    ParameterNameDiscoverer defaultParameterNameDiscoverer = new DefaultParameterNameDiscoverer();

    private ConcurrentHashMap<String,Expression> cacheExpression = new ConcurrentHashMap<>();

    @Around("within(com.xxx.cloud.assets.serviceImpl..*) && @annotation(syncEs)")
    public Object syncEs(ProceedingJoinPoint joinPoint, SyncEs syncEs) throws Throwable {

        try {
            Object result = joinPoint.proceed();
            syncEsInner(joinPoint, syncEs);
            return result;

        } catch (Throwable throwable) {
            throw throwable;
        }

    }

    private void syncEsInner(ProceedingJoinPoint joinPoint, SyncEs syncEs) {
        // 切面所在类
        Object target = joinPoint.getTarget();

        String methodName = joinPoint.getSignature().getName();

        Method method = null;
        for (Method m : target.getClass().getMethods()) {
            if (m.getName().equals(methodName)) {
                method = m;
                break;
            }
        }

        EvaluationContext evaluationContext = new MethodBasedEvaluationContext(target, method, joinPoint.getArgs(),
                defaultParameterNameDiscoverer);

        if (StringUtils.isNotEmpty(syncEs.indexId())) {
            Integer indexId = getExpression(syncEs.indexId()).getValue(evaluationContext, Integer.class);
            if (indexId != null && indexId > 0) {
                // 如果定义了根据id更新,更新完直接return
                ...
                return;
            }
        }

        String[] conditions = syncEs.conditions();

        String[] conditionKeys = syncEs.conditionKeys();

        EsLogical logical = syncEs.esLogical();

        if (conditions == null || conditionKeys == null || conditions.length ==0 || conditions.length != conditionKeys.length) {
            Log.error("无法更新数据到es,因为注解中的数据非法!");
            return;
        }

        ...

    }

    private Expression getExpression(String expression) {
        if(cacheExpression.containsKey(expression)){
            return cacheExpression.get(expression);
        }else {
            Expression expressionObject = null;
            synchronized (SyncEsAspect.class) {
                expressionObject = expressionParser.parseExpression(expression);
            }
            cacheExpression.put(expression,expressionObject);
            return expressionObject;
        }

    }

}

4.使用

@Override
@SyncEs(indexId = "#model.id")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })
public int saveAssetCard(AssetCardModel model, String remark) throws AssetException {
    ...
}





AOP(面向切面编程)是一种编程范式,可以通过在不修改目标对象代码的情况下,对其进行增强或拦截,实现例如日志记录、性能统计、事务管理等功能。自定义注解是Java语言的一种元数据,可以用于在代码添加额外的信息,例如标记某个方法需要进行权限验证、标记某个类是单例模式等。 将AOP自定义注解搭配使用,可以更方便地实现特定功能。例如,可以使用自定义注解标记需要进行性能统计的方法,在AOP拦截这些方法,并在方法执行前后记录方法的执行时间等信息。 具体实现步骤如下: 1. 定义自定义注解,例如: ``` @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface PerformanceLog { String value() default ""; } ``` 2. 定义AOP切面,例如: ``` @Aspect @Component public class PerformanceLogAspect { @Around("@annotation(com.example.annotations.PerformanceLog)") public Object performanceLog(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); Object result = joinPoint.proceed(); long endTime = System.currentTimeMillis(); String methodName = joinPoint.getSignature().getName(); String className = joinPoint.getTarget().getClass().getSimpleName(); String logMsg = "Method [" + className + "." + methodName + "] took " + (endTime - startTime) + " ms."; System.out.println(logMsg); return result; } } ``` 3. 在目标方法上添加自定义注解,例如: ``` @Service public class UserService { @PerformanceLog("getUserById") public User getUserById(Long id) { //... } } ``` 这样,在调用getUserById方法时,AOP会拦截该方法,并输出方法的执行时间等信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值