Spring中AOP的模拟实现

来源:互联网 发布:可变数据印刷软件价格 编辑:程序博客网 时间:2024/04/30 11:52
什么是AOP?
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面
1.面向切面编程提供声明式事务管理
2.spring支持用户自定义的切面

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

aop框架具有的两个特征:
1.各个步骤之间的良好隔离性
2.源代码无关性

前提:要实现AOP的模拟就要知道动态代理,Spring中使用了两种动态代理方式,一种是基于JDK的动态代理,一种是基于CGlib的动态代理。为什么会有两种,那是因为JDK的动态代理只能是针对接口。

先看下面的代码dao层
Java代码 复制代码收藏代码
  1. package com.lbx.dao; 
  2.  
  3. import com.lbx.model.User; 
  4.  
  5. public interface UserDAO { 
  6.     public void save(User user); 
  7.     //public void delete(); 
dao实现层
Java代码 复制代码收藏代码
  1. package com.lbx.dao.impl; 
  2.  
  3. import com.lbx.dao.UserDAO; 
  4. import com.lbx.model.User; 
  5.  
  6. public class UserDAOImplimplements UserDAO { 
  7.  
  8.     @Override 
  9.     public void save(User user) { 
  10.          
  11.         System.out.println("a user saved!!!"); 
  12.  
  13.     } 
  14.      
  15.     /*public void delete(){
  16.         System.out.println("UserDAOImpl.delete()");
  17.     }
  18. */ 
现在我们要在User的save之前和之后做一些处理(拦截器),我们先看一种最简单的方法(在类中加代码)
Java代码 复制代码收藏代码
  1. package com.lbx.dao.impl; 
  2.  
  3. import com.lbx.dao.UserDAO; 
  4. import com.lbx.model.User; 
  5.  
  6. public class UserDAOImpl1implements UserDAO { 
  7.  
  8.     @Override 
  9.     public void save(User user) { 
  10.          
  11.         System.out.println("method start...."); 
  12.          
  13.         System.out.println("a user saved!!!"); 
  14.          
  15.         System.out.println("method stoped..."); 
  16.  
  17.     } 
  18.  
显然,这是可以的,但是这样明显就不好,第一代码没可重用性,第二这是在知道源码的情况下,现实中我们有很多情况都不知道源码,在这种情况下,明显这方式就不行了。下面就是第二种解决方案:
Java代码 复制代码收藏代码
  1. package com.lbx.dao.impl; 
  2.  
  3. import com.lbx.model.User; 
  4.  
  5. public class UserDAOImpl2extends UserDAOImpl{ 
  6.  
  7.     public void save(User user) { 
  8.          
  9.         System.out.println("method start...."); 
  10.         super.save(user); 
  11.         System.out.println("method stoped....."); 
  12.          
  13.     } 
  14.  
先让一个类实现了那个接口,然后要用的类继承那个实现类,这样也可以达到目的(其实这就是一种“组合模式”),这种方式在一定的程度上是利用的资源,代码的重用性。但是还是不好,当我们要做很多的处理的时候,这样我们就要组合和多的类,明显就不好。下面是第三种:使用动态代理。                       先看处理方法(拦截器)
Java代码 复制代码收藏代码
  1. package com.lbx.interceptor; 
  2.  
  3. public class UserInterceptor { 
  4.  
  5.     //第一个拦截方法 
  6.     public void method1(){ 
  7.         System.out.println("UserInterceptor.method1()"); 
  8.     } 
  9.      
  10.     //第二个拦截方法 
  11.     public void method2(){ 
  12.         System.out.println("UserInterceptor.method2()"); 
  13.     } 
  14.      
产生代理的类,实现InvocationHandler接口
Java代码 复制代码收藏代码
  1. package com.lbx.interceptor; 
  2.  
  3. import java.lang.reflect.InvocationHandler; 
  4. import java.lang.reflect.Method; 
  5.  
  6. public class ProxyHandlerimplements InvocationHandler { 
  7.      
  8.     //创建需要代理的目标对象 
  9.     private Object targer; 
  10.     //创建拦截器的实例 
  11.     UserInterceptor u = new UserInterceptor(); 
  12.      
  13.     public Object invoke(Object proxy, Method method, Object[] args) 
  14.             throws Throwable { 
  15.         Object result = null
  16.  
  17.         //if(method.getName().equals("save")){ 
  18.             u.method1(); 
  19.             result = method.invoke(targer, args); 
  20.             u.method2(); 
  21.         //}else{ 
  22.             //result = method.invoke(targer, args); 
  23.         //} 
  24.          
  25.         return result; 
  26.     } 
  27.      
  28.     //用于设置传人目标对象的方法 
  29.     public void setTarger(Object o){ 
  30.         this.targer = o; 
  31.     } 
  32.  
获得代理的实例类
Java代码 复制代码收藏代码
  1. package com.lbx.interceptor; 
  2.  
  3. import java.lang.reflect.Proxy; 
  4.  
  5. import com.lbx.dao.impl.UserDAOImpl; 
  6.  
  7. public class UserProxyFactory { 
  8.  
  9.     public static Object getProxy(Object object){ 
  10.         ProxyHandler p = new ProxyHandler(); 
  11.         p.setTarger(object); 
  12.         return Proxy.newProxyInstance(UserDAOImpl.class.getClassLoader(), object.getClass().getInterfaces(), p); 
  13.     }  
  14.      
服务层使用动态代理
Java代码 复制代码收藏代码
  1. package com.lbx.service; 
  2.  
  3. import com.lbx.dao.UserDAO; 
  4. import com.lbx.dao.impl.UserDAOImpl; 
  5. import com.lbx.interceptor.UserProxyFactory; 
  6. import com.lbx.model.User; 
  7.  
  8. public class UserService { 
  9.      
  10.     //private UserDAO userDAO = new UserDAOImpl1();   //第一种就是写死,直接在方法里写 
  11.     //private UserDAO userDAO = new UserDAOImpl2();     //第二种就是通过继承来实现(方法执行前后加一些业务逻辑) 
  12.     //private UserDAO userDAO = new UserDAOImpl3();       //第三种是通过组合来完成的 
  13.     UserDAO userDAO = new UserDAOImpl(); 
  14.     UserDAO u = null
  15.      
  16.     Object object = UserProxyFactory.getProxy(userDAO); 
  17.      
  18.     /*public UserDAO getUserDAO() {
  19.         return userDAO;
  20.     }
  21.     public void setUserDAO(UserDAO userDAO) {
  22.         this.userDAO = userDAO;
  23.     }*/ 
  24.  
  25.     /*public void add(User user){
  26.         this.userDAO.save(user);
  27.     }*/ 
  28.      
  29.     public void add(User user){ 
  30.         if(object instanceof UserDAO){ 
  31.             u = (UserDAO)object; 
  32.         } 
  33.         u.save(user); 
  34.         //u.delete(); 
  35.     } 
  36.      

原创粉丝点击