zoukankan      html  css  js  c++  java
  • spring aop 的一个demo(未完,待完善)

    假设我们有这样的一个场景 : 对于一个类的众多方法,有些方法需要从缓存读取数据,有些则需要直接从数据库读取数据。怎样实现呢?

    实现方案有多种。下面我说下常见的几种实现方案 :

    1、直接采用spring xml、或者  annotation AOP完成。但个人认为这种方案似乎有点不是很完美。

    原因 :  ①、如果只有针对这个类做切面拦截,这种方案是没有问题的,只需对需要走DB(or 缓存,两者择一)的方法配置切面。

        ②、那如果是多个类呢?统一做一个切面,对指定方法拦截,如selectXXX。但,还要考虑个特殊场景,每个人的代码风格不一致,你不能限制

        别人的风格,查询他就偏偏用queryXXX来命令。你能拦截到么?

    2、采用 ProxyFactory 拦截处理, 并且用java自定义的annotation来作为是否需要走缓存的方法唯一标识。(实现得不是很好,后期会持续优化,见谅

    看下代码

    1)自定义注解,标识是否需要走缓存

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface CacheAnnotition {
    
    }

    2)接口定义

    public interface UserReadService {
        
        @CacheAnnotition
        public UserInfo getUserInfoById(Long id);
        
        public UserInfo getUserInfoByName(String name);
    }
    @Component("userReadService")
    public class UserReadServiceImpl implements UserReadService {
    
        @Override
        public UserInfo getUserInfoById(Long id) {
            System.out.println("获取用户信息");
            return null;
        }
        
        @Override
        public UserInfo getUserInfoByName(String name) {
            // TODO Auto-generated method stub
            return null;
        }
    
    }
    View Code
    public interface PeopleReadService {
        
        @CacheAnnotition
        public UserInfo getPeopleInfoById(Long id);
        
        public UserInfo getPeopleInfoByName(String name);
    }
    @Component("peopleReadService")
    public class PeopleReadServiceImpl implements PeopleReadService {
    
        @Override
        public UserInfo getPeopleInfoById(Long id) {
            System.out.println("getPeopleInfoById : 获取用户信息");
            return null;
        }
    
        @Override
        public UserInfo getPeopleInfoByName(String name) {
            // TODO Auto-generated method stub
            return null;
        }
    
    }
    View Code

    3)拦截处理核心逻辑

    public class ProxyFactoryDemo {
    
        public static Map<String, Class<?>> beanMap = new HashMap<String, Class<?>>();
        public static Map<String, Class<?>> instanceMap = new HashMap<String, Class<?>>();
    
        public static List<Object> proxyObjs = new ArrayList<Object>();
    
        static {
            beanMap.put("userReadService", UserReadService.class);
            beanMap.put("peopleReadService", PeopleReadService.class);
    
            instanceMap.put("userReadService", UserReadServiceImpl.class);
            instanceMap.put("peopleReadService", PeopleReadServiceImpl.class);
        }
    
        public static void main(String[] args) throws Exception {
            initProxyObjs();
            
            for(Object proxy : proxyObjs) {
                if (proxy instanceof UserReadService) {
                    UserReadService u = (UserReadService)proxy;
                    u.getUserInfoById(null);
                    u.getUserInfoByName(null);
                } else if(proxy instanceof PeopleReadService) {
                    PeopleReadService p = (PeopleReadService)proxy;
                    p.getPeopleInfoById(null);
                    p.getPeopleInfoByName(null);
                }
            }
        }
    
        public static void initProxyObjs() throws InstantiationException, IllegalAccessException {
            Iterator<String> it = beanMap.keySet().iterator();
            while (it.hasNext()) {
                String beanName = it.next();
                Class<?> beanClass = instanceMap.get(beanName);
                Object proxy = getProxy(beanClass.newInstance(), beanMap.get(beanName), beanName);
                proxyObjs.add(proxy);
            }
        }
    
        public static Object getProxy(final Object target, Class<?> aClass, final String beanName) {
    
            ProxyFactory factory = new ProxyFactory();
    
            factory.addInterface(aClass);
            factory.setTarget(target);
            factory.setOpaque(true);
            factory.addAdvice(new MethodInterceptor() {
    
                @Override
                public Object invoke(MethodInvocation invocation) throws Throwable {
                    System.out.println("start");
                    if (invocation.getMethod().isAnnotationPresent(CacheAnnotition.class)) {
                        System.out.println(invocation.getMethod().getName() + "需要走缓存");
                    } else {
                        System.out.println(invocation.getMethod().getName() + "不需要走缓存");
                    }
                    Object obj = invocation.proceed();
                    System.out.println("end");
                    return obj;
                }
            });
    
            return factory.getProxy(factory.getClass().getClassLoader());
        }
    }
  • 相关阅读:
    CMake 手册详解(五)
    linux 学习资料、Linux学习书籍(入门书籍、shell编程)推荐
    linux shell 管道命令(pipe)使用及与shell重定向区别
    linux shell “(())” 双括号运算符使用
    web签名验证程序【跨服务器、中文字符签名方法】php为例
    linux shell 脚本实现tcp/upd协议通讯(重定向应用)
    web程序乱码深入分析【基础原理篇】php为例
    php empty,isset,is_null比较(差异与异同)
    php 实现进制转换(二进制、八进制、十六进制)互相转换
    php通过文件头检测文件类型通用类(zip,rar…)
  • 原文地址:https://www.cnblogs.com/chenmo-xpw/p/5540592.html
Copyright © 2011-2022 走看看