添加bean的监听

原理:利用spring bean 的监听,在所有的bean 初始化完成之后,能够接收到动作,在这会儿,可以利用spring获取到对应annotation、type的类,利用反射可以做到很多事情。

  注意:spring的反射是cglib工具构建的,所以此时需要使用一个工具类获取到原始的javabean。

1、注册监听器

@Service
@Lazy(true)
public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
}

2、完整的代码(包含获取bean,反射)

package com.qysxy.erp.common.listener;

import com.qysxy.erp.constants.ShiroConstants;
import com.qysxy.erp.framework.shiro.annotation.PermissionDesc;
import com.qysxy.erp.util.reflect.AopTargetUtils;
import com.yizhilu.os.core.service.cache.MemCache;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Description 利用spring的监听获取bean,
 * @Author fuguangli businessfgl@163.com
 * @Create date:    2017/8/30
 */
@Service
@Lazy(true)
public class ShiroApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    private MemCache memCache = MemCache.getInstance();

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
//        ReflectionUtils.getAllDeclaredMethods()
        Map<String, String> savePerms = new HashMap<>();
        Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(PermissionDesc.class);
        if (beans != null) {
            Set<String> keys = beans.keySet();
            for (String key : keys) {
                Object o = null;
                try {
                    o = AopTargetUtils.getTarget(beans.get(key));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                Class clazz = o.getClass();
                Method[] methods = clazz.getMethods();
//                Method[] methods = ReflectionUtils.getAllDeclaredMethods(o.getClass());
                if (methods != null) {
                    for (Method method : methods) {
//                        method.setAccessible(true);
                        Annotation[] annos = method.getAnnotations();
                        PermissionDesc permissionDesc = null;
                        RequiresPermissions requiresPermissions = null;
                        for (Annotation a : annos) {
                            if (a.annotationType().equals(PermissionDesc.class)) {
                                permissionDesc = (PermissionDesc) a;
                            }
                            if (a.annotationType().equals(RequiresPermissions.class)) {
                                requiresPermissions = (RequiresPermissions) a;
                            }
                        }
                        if (permissionDesc != null && requiresPermissions != null) {
                            String desc = permissionDesc.value();
                            String[] perms = requiresPermissions.value();
                            for (String perm : perms) {
                                /*TODO:此处应存入缓存  perm:desc*/
                                System.out.println(perm + ":" + desc);
                                savePerms.put(perm, desc);
                            }
                        }
                    }
                }
            }
            if (savePerms.size() != 0) {
                memCache.set(ShiroConstants.PERMS_KEY, savePerms);//默认存储24小时,用于新建权限的时候的权限钥匙
            }
        }

    }
}

3、获取原始javabean的工具类

package com.qysxy.erp.util.reflect;

import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.AopProxy;
import org.springframework.aop.support.AopUtils;

import java.lang.reflect.Field;

public class AopTargetUtils {
 
     
    /**
     * 获取 目标对象
     * @param proxy 代理对象
     * @return 目标对象
     * @throws Exception
     */
    public static Object getTarget(Object proxy) throws Exception {
        if(!AopUtils.isAopProxy(proxy)) {
            return proxy;//不是代理对象
        }
 
        if(AopUtils.isJdkDynamicProxy(proxy)) {
            return getJdkDynamicProxyTargetObject(proxy);
        } else { //cglib
            return getCglibProxyTargetObject(proxy);
        }
    }
 
 
    private static Object getCglibProxyTargetObject(Object proxy) throws Exception {
        Field field = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
        field.setAccessible(true);
        Object dynamicAdvisedInterceptor = field.get(proxy);
         
        Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
        advised.setAccessible(true);
         
        Object target = ((AdvisedSupport)advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
         
        return target;
    }
 
 
    private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
        Field field = proxy.getClass().getSuperclass().getDeclaredField("h");
        field.setAccessible(true);
        AopProxy aopProxy = (AopProxy) field.get(proxy);
         
        Field advised = aopProxy.getClass().getDeclaredField("advised");
        advised.setAccessible(true);
         
        Object target = ((AdvisedSupport)advised.get(aopProxy)).getTargetSource().getTarget();
         
        return target;
    }
     
}

 

posted @ 2017-09-05 10:52  构建巨人肩膀  阅读(628)  评论(0编辑  收藏  举报