我们在很多时候,并不能直接使用spring aop功能,需要自己实现代理对java代码进行aop操作。这里使用手动代理的方式对AOP进行处理。
实践一、定义一个注解用于需要特殊处理的方法
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface StepAnnotation {
String name();
}
二、定义一个BeanPostProcessor 用于对需要特殊处理方法用代理代替原有类
@Configuration
public class StepBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object o, String beanName) throws BeansException {
try {
Method[] methods = o.getClass().getMethods();
for (Method method : methods) {
StepAnnotation annotation = method.getAnnotation(StepAnnotation.class);
if (annotation != null) {
Object o1 = PluginStepProxyFactory.getInstance(o.getClass());
Field[] allFields = FieldUtils.getAllFields(o.getClass());
for (Field field : allFields) {
if (field.getDeclaredAnnotations().length == 0) {
continue;
}
field.setAccessible(true);
field.set(o1, field.get(o));
}
return o1;
}
}
} catch (IllegalAccessException e) {
CommonLogUtil.error("StepBeanPostProcessor.postProcessBeforeInitialization fail", e);
}
return o;
}
@Override
public Object postProcessAfterInitialization(Object o, String beanName) throws BeansException {
return o;
}
}
三、具体创建代理实现类
public class PluginStepProxyFactory {
public static T getInstance(Class clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback((MethodInterceptor)(o,method,objects,methodProxy)->{
StepAnnotation stepAnnotation = method.getAnnotation(StepAnnotation.class);
if (stepAnnotation != null) {
TimeInterval timer = DateUtil.timer();
Object res = methodProxy.invokeSuper(o, objects);
long interval = timer.intervalMs();
CommonLogUtil.info("step " + stepAnnotation.name() + "time 消耗" + interval + "ms,result is:" + res);
return res;
}
return methodProxy.invokeSuper(o, objects);
});
return (T) enhancer.create();
}
}
四、使用test类进行测试
public ListgetData(){ LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); testStep(); return testService.list(queryWrapper); } @StepAnnotation(name = "测试步骤") public String testStep() { try { CommonLogUtil.info("调用步骤111"); Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } return "step--"; }



