• 添加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;
        }
         
    }
  • 相关阅读:
    娓娓道来c指针 (4)解析c的声明语句
    Snail—UI学习之UITextField
    E
    Qt录音机
    著名的英文搜索引擎
    java中Map,List与Set的差别
    Android图片处理:识别图像方向并显示
    Unity3D中组件事件函数的运行顺序
    Android屏幕density, dip等相关概念总结
    Codeforces Round #257 (Div. 2)
  • 原文地址:https://www.cnblogs.com/yuan951/p/7477497.html
Copyright © 2020-2023  润新知