zoukankan      html  css  js  c++  java
  • 尚学堂Spring视频教程(五):Spring AOP

      在第一节中,我们自己模拟了一个Spring,实现一个保存用户的操作,假如现在有一个需求,在保存的时候记录日志,该怎么做呢?  

      暂且将记录日志操作就简单的变为在保存用户前输出一句话“save start...”,不建议直接在UserDAOImpl的save方法里写代码,因为我们有时候可能得不到源码,这个时候可以添加一个UserDAOImpl2继承UserDAOImpl,然后调用父类的save方法

    package com.bjsxt.dao.impl;
    
    import com.bjsxt.model.User;
    
    public class UserDAOImpl2 extends UserDAOImpl {
        @Override
        public void save(User user) {
            
            System.out.println("save start...");
            super.save(user);
            
        }
    }
    UserDAOImpl2

      注:配置文件被注入到UserService的bean的class要改为UserDAOImpl2,下面也一样

      看似实现了效果,但是这样很不灵活,因为只能继承一个类,而且父类发生变化,子类也必须跟着做出改变,我们可以再添加一个类继承UserDAOImpl,但是采用组合的方法

    package com.bjsxt.dao.impl;
    
    import com.bjsxt.aop.LogInterceptor;
    import com.bjsxt.dao.UserDAO;
    import com.bjsxt.model.User;
    
    public class UserDAOImpl3 implements UserDAO {
        
        private UserDAO userDAO = new UserDAOImpl();
        
        public void save(User user) {
            System.out.println("save start...");
            /*new LogInterceptor().beforeMethod(null);*/
            userDAO.save(user);
            
            
        }
    
        /*public void delete() {
            // TODO Auto-generated method stub
            
        }*/
    }
    UserDAOImpl3

      问题又来了,如果系统有500个需要被注入的bean,每个bean都有一些操作需要被记录日志,难道要组合500个bean来实现这个功能吗?

      实际上可以给UserDAOImpl产生了一个代理,我们知道在代理模式中代理类除了可以调用目标对象的方法,也可以在方法前后加入自己的逻辑,在这里就是日志记录

      在JAVA基础知识:代理这篇文章中,介绍了Proxy类的静态方法newProxyInstance,这个方法需要三个参数,第一个是类装载器,第二个是目标对象的接口,第三个是InvocationHandler,这个最重要,定义了一个invoke方法,方法中可以调用目标对象的方法,也可以添加日志记录的逻辑代码

      新建一个包com.bjsxt.aop,添加类LogInterceptor继承InvocationHandler

    package com.bjsxt.dao.impl;
    
    import com.bjsxt.dao.UserDAO;
    import com.bjsxt.model.User;
    
    
    public class UserDAOImpl implements UserDAO {
    
        public void save(User user) {
            
            //Hibernate
            //JDBC
            //XML
            //NetWork
            System.out.println("user saved!");
        }
    
        public void delete() {
            System.out.println("user deteleted");
            
        }
    
    }
    UserDAOImpl
    package com.bjsxt.aop;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class LogInterceptor implements InvocationHandler {
        private Object target;
        
        public Object getTarget() {
            return target;
        }
    
        public void setTarget(Object target) {
            this.target = target;
        }
    
        public void beforeMethod(Method m) {
            
            System.out.println(m.getName() + " start");
        }
    
        public Object invoke(Object proxy, Method m, Object[] args)
                throws Throwable {
            beforeMethod(m);
            m.invoke(target, args);
            return null;
        }
    }
    InvocationHandler接口的实现类
        @Test
        public void testProxy() {
            UserDAO userDAO = new UserDAOImpl();
            LogInterceptor li = new LogInterceptor();
            li.setTarget(userDAO);
            UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);
            System.out.println(userDAOProxy.getClass());
            userDAOProxy.delete();
            userDAOProxy.save(new User());
            
        }
    单元测试

      我们只需要写一次日志记录的代码,就完成delete和add用户的日志记录工作

      项目结构如下:

  • 相关阅读:
    课堂作业04 2017.10.27
    课程作业 03 动手动脑 2017.10.20
    课程作业 03 2017.10.20
    HDU 3974 Assign the task
    POJ 2155 Matrix
    POJ 2481 Cows
    HDU 3038 How Many Answers Are Wrong
    CS Academy Array Removal
    POJ_1330 Nearest Common Ancestors LCA
    CF Round 427 D. Palindromic characteristics
  • 原文地址:https://www.cnblogs.com/SamFlynn/p/4604148.html
Copyright © 2011-2022 走看看