jfinal使用注解实现aop,spring ioc容器一体化

/**
 * aop自动注入注解
 * @version 1.0
 * @create_at 2017年7月24日下午9:21:12
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
public @interface AopBean {
}

package com.information.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
public @interface Aop {
    String value() default "";
}

//次注解可配合service层拦截器使用
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.TYPE})
@Documented
public @interface Interceptor {
    String value() default "";
    Class<? extends com.jfinal.aop.Interceptor>[] target();
}

/**
 * aop注入插件
 * @version 1.0
 * @create_at 2017年7月25日上午8:14:05
 */
public class AopBeanPlugin<T> implements IPlugin{

    private static final Log LOG=Log.getLog(AopBeanPlugin.class);
        private List<String> beanList=new ArrayList<String>();
    @SuppressWarnings("rawtypes")
    private List<Class> excludeClasses=new ArrayList<Class>();
    private boolean autoScan;
    public AopBeanPlugin<T> setPackageName(String... packageName){
       if(packageName.length==0||packageName==null)
        throw new NullPointerException("packageName can not be null");
        for(String pack:packageName){
          beanList.add(pack);
        }
     return this;
    }
    public boolean isAutoScan() {
         return autoScan;
    }

    @SuppressWarnings("rawtypes")
    public AopBeanPlugin setAutoScan(boolean autoScan) {
        this.autoScan = autoScan;
        return this;
    }
@Override
public boolean start() {
    List<Class<? extends T>> targetClass = PackageUtil.scanPackage(beanList);
        for(Class<? extends T> target:targetClass){
        if(excludeClasses.contains(target)){
             continue;
        }
    Annotation[] annotations = target.getAnnotations();
        if(target.getAnnotations() != null){
        Object object = null;
        String value = null;
        for(Annotation annotation : annotations){
        if(annotation instanceof Aop){
        object= Duang.duang(target.getName(),target);
        value=target.getAnnotation(Aop.class).value();
        }else if(annotation instanceof Interceptor){
        Class<? extends com.jfinal.aop.Interceptor>[] interceptorClass = ((Interceptor) annotation).target();
        value =((Interceptor) annotation).value();
        object = Duang.duang(target.getName(),target,interceptorClass);
        }
    }
    String simpleName=target.getSimpleName().substring(1, target.getSimpleName().length());
    String key=StrKit.toLowerCaseFirst(target.getSimpleName())+simpleName;
    if(object != null){
        if(StrKit.isNotEmpoty(value)){
        AopManger.beanMap.put(value, object);
    }else{
        AopManger.beanMap.put(key, object);
    }
        LOG.info("create aop bean "+object);
   }
}
   continue;
}
     return true;
}

@Override
public boolean stop() {
      return true;
}
public AopBeanPlugin<T> addExcludeClasses(Class<?>... clazzes) {
        if (clazzes != null) {
            for (Class<?> clazz : clazzes) {
                excludeClasses.add(clazz);
            }
        }
        return this;
    }
}

}
/**
 * aop对象注入拦截器
 * @version 1.0
 * @create_at 2017年7月24日下午9:18:12
 */
public class AopInterceptor implements Interceptor{
private  ApplicationContext ctx;
public AopInterceptor(ApplicationContext ctx){
this.ctx = ctx;
}
public AopInterceptor(){}
@Override
public void intercept(Invocation inv) {
Controller controller = inv.getController();
Field[] fields = controller.getClass().getDeclaredFields();
//controller层aop的自动注入
for (Field field : fields) {
Object bean = null;
if (field.isAnnotationPresent(AopBean.class)){
bean = AopManger.beanMap.get(field.getName());
Class<?> cla = field.getType();
//service层aop的自动注入
for(Field f : cla.getDeclaredFields()){
Object serviceBean = null;
if(f.isAnnotationPresent(AopBean.class)){
serviceBean = AopManger.beanMap.get(f.getName());
}else if(f.isAnnotationPresent(Autowired.class)){
serviceBean = ctx.getBean(f.getName());
}
if(serviceBean != null){
try {
f.setAccessible(true);
f.set(bean, serviceBean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new NullPointerException("Field can not be null");
}
}
}
}else if(field.isAnnotationPresent(Autowired.class)){
bean = ctx.getBean(field.getName());
}else{
continue ;
   }
try {
if (bean != null) {
field.setAccessible(true);
field.set(controller, bean);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
inv.invoke();
}
}

具体使用方式如下
@Aop
public class SystemAdminService extends BaseService{
}

public class LoginController extends BaseController{
    @AopBean
private SystemRoleService systemRoleService;
    
    @Autowired
private OnlineManger onlineManger;
    }
注:(此方法只对controller和service层有效)

评论区

爪爪

2017-07-25 09:04

有点多啊,感觉还不如duang

JFinal

2017-07-25 10:30

很有探索精神,赞一个

穿越123

2017-07-25 10:38

@JFinal 谢谢波总,请问波总有需要改善的地方吗

JFinal

2017-07-25 10:46

@穿越123 就目前来看代码挺简洁的,先用上一段时间,逐步打磨就好

希望能直接编辑这个贴子,将代码部分用插入代码功能来做,这样代码就会有高亮显示效果了,看这里的代码就是有高亮显示的:http://www.jfinal.com/project/1

穿越123

2017-07-25 10:50

@JFinal 谢谢波总指导

JFinal

2017-07-25 11:13

@穿越123 感谢支持

穿越123

2017-07-26 08:30

@爪爪 用注解更方便啊,代码简洁

木头人liqiu

2017-07-27 16:59

@爪爪厉害

Irin.Chan

2017-07-29 22:53

AService(Aop Support) ----use----> BService(Aop not Support)。
http://www.jfinal.com/share/362
海哥的jboot有更好的实现。
不过目前应该还有个问题:
http://www.jfinal.com/feedback/1729

穿越123

2017-07-31 10:11

@Irin.Chan 什么意思啊

穿越123

2017-07-31 11:59

@Irin.Chan 有什么问题,你先说下

穿越123

2017-07-31 13:35

@Irin.Chan 你的意思是在service层中使用before(Tx.class),aop功能没用??

穿越123

2017-07-31 13:47

@Irin.Chan 有影响在service层的事物吗,我试了,不会呀

Irin.Chan

2017-07-31 15:00

@穿越123 没事了,把你代码拿下来才发现,这个Aop仅限于Controller层使用,并不支持在Service层,所以Service层还是需要手动Enhance,只支持ByName,不支持ByType,少了Scan Class的工具类。

穿越123

2017-07-31 16:25

@Irin.Chan 你不说我还没考虑到service层的使用,谢谢提意见

穿越123

2017-07-31 20:44

@JFinal 波总,请教您一个问题,目前发现这个注解只能适用于controller层,怎么让它在service层也能起作用

JFinal

2017-07-31 23:52

@穿越123 jfinal 手册有专门讲如何在 service 层使用注解

djs19960601

2017-09-08 09:15

是不是spring可用的插件就可以这样用了?

穿越123

2017-09-08 10:44

@Irin.Chan @Irin.Chan 目前service层aop已经可以使用了,完全不会啊导致service层拦截器失效

穿越123

2017-09-08 10:46

@djs19960601 对的,只限于controller层和service层

穿越123

2017-09-10 21:04

@djs19960601 是的,你可以试试看,好不好用,欢迎提问题

穿越123

2017-09-10 21:05

@Irin.Chan service层aop已经可以使用了,现在

Irin.Chan

2017-09-11 16:37

@穿越123 666, 好久没逛JFinal社区了,最近比较忙, 你自己测试下吧,在Service中的两个方法都加上拦截器,在第一个方法中直接调用第二个方法,然后Controller调用第一个方法,看看两个拦截器是否有效。

穿越123

2017-09-12 11:18

@Irin.Chan 绝对没有问题的,因为我这个本身就是aop

Irin.Chan

2017-09-14 10:47

@穿越123 你上面的代码少了ApplicationContext,还有一些类,我没法测试,你看看我这里写的测试用例,加上你的注解试试跑一下,看看DemoController的注释
https://git.oschina.net/itc10/jfinal-study/tree/master/ioc-support/src/main/java/com/yaolin/jfinal

热门分享

扫码入社