• Spring中AOP的模拟实现


    什么是AOP?
    面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面
    1.面向切面编程提供声明式事务管理
    2.spring支持用户自定义的切面

    面向切面编程(aop)是对面向对象编程(oop)的补充,
    面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。
    AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象,
    是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。

    aop框架具有的两个特征:
    1.各个步骤之间的良好隔离性
    2.源代码无关性
    前提:要实现AOP的模拟就要知道动态代理,Spring中使用了两种动态代理方式,一种是基于JDK的动态代理,一种是基于CGlib的动态代理。为什么会有两种,那是因为JDK的动态代理只能是

    针对接口。

    先看下面的代码dao层
    Java代码     
    package com.lbx.dao;   
    import com.lbx.model.User;   
    public interface UserDAO {   
         public void save(User user);   
         //public void delete();   

    dao实现层
    Java代码     
    package com.lbx.dao.impl;   

    import com.lbx.dao.UserDAO;   
    import com.lbx.model.User;   
       
    public class UserDAOImpl implements UserDAO {   
       
         @Override  
         public void save(User user) {   
                
             System.out.println("a user saved!!!");   
       
         }   
          
         /*public void delete(){  
             System.out.println("UserDAOImpl.delete()");  
         }  
    */  

    现在我们要在User的save之前和之后做一些处理(拦截器),我们先看一种最简单的方法(在类中加代码)
    Java代码     
    package com.lbx.dao.impl;   
     
    import com.lbx.dao.UserDAO;   
    import com.lbx.model.User;   
      
    public class UserDAOImpl1 implements UserDAO {   
      
        @Override  
        public void save(User user) {   
                
             System.out.println("method start....");   
                
             System.out.println("a user saved!!!");   
                
             System.out.println("method stoped...");   
       
         }   
       

    显然,这是可以的,但是这样明显就不好,第一代码没可重用性,第二这是在知道源码的情况下,现实中我们有很多情况都不知道源码,在这种情况下,明显这方式就不行了。下面就是第二

    种解决方案:
    Java代码     
    package com.lbx.dao.impl;   
    import com.lbx.model.User;
      
    public class UserDAOImpl2 extends UserDAOImpl{   
       
         public void save(User user) {   
               
             System.out.println("method start....");   
             super.save(user);   
             System.out.println("method stoped.....");   
                
         }   
       

    先让一个类实现了那个接口,然后要用的类继承那个实现类,这样也可以达到目的(其实这就是一种“组合模式”),这种方式在一定的程度上是利用的资源,代码的重用性。但是还是不好

    ,当我们要做很多的处理的时候,这样我们就要组合和多的类,明显就不好。下面是第三种:使用动态代理。                       先看处理方法(拦截器)
    Java代码     
    package com.lbx.interceptor;   
    public class UserInterceptor {   
        //第一个拦截方法   
         public void method1(){   
             System.out.println("UserInterceptor.method1()");   
         }   
            
         //第二个拦截方法   
         public void method2(){   
             System.out.println("UserInterceptor.method2()");   
         }   
            

    产生代理的类,实现InvocationHandler接口
    Java代码     
    package com.lbx.interceptor;   
    import java.lang.reflect.InvocationHandler;   
    import java.lang.reflect.Method;   
    public class ProxyHandler implements InvocationHandler {   
            
         //创建需要代理的目标对象   
        private Object targer;   
         //创建拦截器的实例   
         UserInterceptor u = new UserInterceptor();   
            
         public Object invoke(Object proxy, Method method, Object[] args)   
                 throws Throwable {   
             Object result = null;   
       
             //if(method.getName().equals("save")){   
                 u.method1();   
                 result = method.invoke(targer, args);   
                 u.method2();   
             //}else{   
                 //result = method.invoke(targer, args);   
             //}   
                
             return result;   
         }   
            
         //用于设置传人目标对象的方法   
         public void setTarger(Object o){   
             this.targer = o;   
         }  


    获得代理的实例类
    Java代码     
    package com.lbx.interceptor;   
    import java.lang.reflect.Proxy;   
    import com.lbx.dao.impl.UserDAOImpl;   
    public class UserProxyFactory {   
      
         public static Object getProxy(Object object){   
             ProxyHandler p = new ProxyHandler();   
             p.setTarger(object);   
             return Proxy.newProxyInstance(UserDAOImpl.class.getClassLoader(), object.getClass().getInterfaces(), p);  
         }    

    服务层使用动态代理
    Java代码     
    package com.lbx.service;   
       
    import com.lbx.dao.UserDAO;   
    import com.lbx.dao.impl.UserDAOImpl;   
    import com.lbx.interceptor.UserProxyFactory;   
    import com.lbx.model.User;   
      
    public class UserService {   
           
         //private UserDAO userDAO = new UserDAOImpl1();   //第一种就是写死,直接在方法里写   
         //private UserDAO userDAO = new UserDAOImpl2();     //第二种就是通过继承来实现(方法执行前后加一些业务逻辑)  
         //private UserDAO userDAO = new UserDAOImpl3();       //第三种是通过组合来完成的   
         UserDAO userDAO = new UserDAOImpl();   
         UserDAO u = null;   
            
         Object object = UserProxyFactory.getProxy(userDAO);   
            
         /*public UserDAO getUserDAO() {  
             return userDAO;  
         }  
      
         public void setUserDAO(UserDAO userDAO) {  
             this.userDAO = userDAO;  
         }*/  
       
         /*public void add(User user){  
             this.userDAO.save(user);  
         }*/  
            
         public void add(User user){   
             if(object instanceof UserDAO){   
                 u = (UserDAO)object;   
             }   
             u.save(user);   
             //u.delete();   
         }  

  • 相关阅读:
    XTREE随笔
    多重共线性
    常用特征选取算法
    最短路径算法的实现(dijskstra):Python
    数据科学的完整学习路径—Python版(转载)
    windows下64位python的安装及机器学习相关包的安装(实用)
    拓扑排序 详解 + 并查集 详解 + 最小生成树(MST)详解 【普利姆算法 + 优先队列优化 & 克鲁斯卡尔算法】
    最短路算法 :Bellman-ford算法 & Dijkstra算法 & floyd算法 & SPFA算法 详解
    在linux下部署项目所用到的基本linux命令
    素数筛 模板
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3165471.html
Copyright © 2020-2023  润新知