Spring AOP
Spring AOP(面向切面编程)
一、谈谈代理模式
代理模式在java 开发中是一种比较常见的设计模式。设计目的旨在为服务类与客户类之间插入其他功能,插入的功能对于调用者是透明的,起到伪装控制的作用。如租房的例子 房客、中介、房东。对应于代理模式中即:客户类 代理类 委托类(被代理类)。
代理模式的两个设计原则:
1. 代理类与委托类具有相似的行为(共同接口)
2. 代理类增强委托类的行为(代理类拥有委托类的引用,同时又有自己的功能实现)
实现代理模式的三要素:
1. 接口
2. 代理角色 代理类拥有真实角色的引用,与真实角色实现共同接口
3. 真实角色 委托类
Uml简图如下:
代理模式分为两类:静态代理和动态代理及批量化代理(aop)
1、静态代理
为某个对象提供一个代理,代理角色固定,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
代码演示:
真实角色和代理角色共同实现这一接口
1 package com.wisezone.test; 2 3 /** 4 * 真实角色和代理角色共同实现这一接口 5 * @author 王东海 6 * @2017年4月29日 7 */ 8 public interface Marry { 9 10 public void toMarry(); 11 }
真实角色(自己)
1 package com.wisezone.test; 2 3 /** 4 * 真实角色(自己) 5 * @author 王东海 6 * @2017年4月29日 7 */ 8 public class You implements Marry { 9 10 @Override 11 public void toMarry() { 12 System.out.println("等了这么久,终于等到你了。。。。"); 13 } 14 15 }
代理角色:婚庆公司
1 package com.wisezone.test; 2 3 /** 4 * 代理角色:婚庆公司 5 * @author 王东海 6 * @2017年4月29日 7 */ 8 public class MarryCompany implements Marry { 9 10 //引入真实角色的引用 11 private You you; 12 13 14 public MarryCompany(You you) { 15 this.you = you; 16 } 17 18 public void before(){ 19 System.out.println("婚礼正在紧张筹备中,请耐心等待。。。"); 20 } 21 22 23 public void after(){ 24 System.out.println("恭喜你现在正式成为已婚人士。。。"); 25 } 26 27 28 @Override 29 public void toMarry() { 30 31 before(); 32 you.toMarry(); 33 after(); 34 } 35 36 }
测试类
1 package com.wisezone.test; 2 3 /** 4 * 测试类 5 * @author 王东海 6 * @2017年4月29日 7 */ 8 public class Test { 9 public static void main(String[] args) { 10 MarryCompany marryCompany = new MarryCompany(new You()); 11 marryCompany.toMarry(); 12 } 13 }
结果:
---------------------------------------------------------------------------------------------------------------------------------------------------
因为静态代理对于代理的角色是固定的,如dao层 20个dao类,如果要对方法的访问权限进行代理,此时需要创建20个静态代理角色,引起类爆炸,无法满足生产上的需要,于是就催生了动态代理的思想。
2、动态代理
相比于静态代理,动态代理在创建代理对象上更加的灵活,它会根据需要通过反射机制在程序运行期动态的为目标对象创建代理对象,代理的行为可以代理多个方法,即满足生产需要的同时又达到代码通用的目的。
动态代理的两种实现方式:
I.jdk实现动态代理。
对于jdk动态代理实现方式比较复杂,回调方式实现 底层原理参考:
http://rejoy.iteye.com/blog/1627405
代码演示:
1 package com.wisezone.test; 2 3 /** 4 * 真实角色和代理角色共同实现这一接口 5 * @author 王东海 6 * @2017年4月29日 7 */ 8 public interface Marry { 9 10 public void toMarry(); 11 }
1 package com.wisezone.test; 2 3 /** 4 * 真实角色(自己) 5 * @author 王东海 6 * @2017年4月29日 7 */ 8 public class You implements Marry { 9 10 @Override 11 public void toMarry() { 12 System.out.println("等了这么久,终于等到你了。。。。"); 13 } 14 15 }
1 package com.wisezone.test; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 /** 7 * jdk实现动态代理 8 * @author 王东海 9 * @2017年4月29日 10 */ 11 public class JDKHandler implements InvocationHandler { 12 13 private Object target; 14 15 16 public JDKHandler(Object target) { 17 super(); 18 this.target = target; 19 } 20 21 /** 22 * 参数1:类加载器 23 * 参数2:目标类实现的所有接口 返回的是一个数组 24 * 参数3:实现InvocationHandler接口对象 25 * @return 26 * Object 27 */ 28 public Object getProxy(){ 29 30 return Proxy.newProxyInstance(this.getClass().getClassLoader(), 31 target.getClass().getInterfaces(), this); 32 } 33 34 public void before(){ 35 System.out.println("婚礼正在紧张筹备中,请耐心等待。。。"); 36 } 37 38 39 public void after(){ 40 System.out.println("恭喜你现在正式成为已婚人士。。。"); 41 } 42 43 44 @Override 45 public Object invoke(Object proxy, Method method, Object[] args) 46 throws Throwable { 47 before(); 48 Object result = method.invoke(target, args);//执行目标类方法 49 after(); 50 return result; 51 } 52 53 }
1 package com.wisezone.test; 2 3 /** 4 * 测试类 5 * @author 王东海 6 * @2017年4月29日 7 */ 8 public class Test { 9 public static void main(String[] args) { 10 JDKHandler jdkHandler = new JDKHandler(new You()); 11 Marry marry = (Marry) jdkHandler.getProxy(); 12 marry.toMarry(); 13 } 14 }
结果:
II.cglib 动态代理实现(了解)
code generator library ,操作字节码。 与jdk提供的代理区别,Proxy:委托类必须有接口,制作过程比较快,执行慢;cglib:委托类可以没有接口,继承的思维来实现相似性,制作代理过程比较慢,执行快。主要:解决没有接口类的代理实现。
代码演示:
1、引入jar包
1 package com.wisezone.test; 2 3 import java.lang.reflect.Method; 4 5 import net.sf.cglib.proxy.Enhancer; 6 import net.sf.cglib.proxy.MethodInterceptor; 7 import net.sf.cglib.proxy.MethodProxy; 8 9 /** 10 * cglib实现动态地理 11 * @author 王东海 12 * @2017年4月29日 13 */ 14 public class CglibInterceptor implements MethodInterceptor { 15 16 private Object target; 17 18 19 public CglibInterceptor(Object target) { 20 super(); 21 this.target = target; 22 } 23 24 public Object getProxy(){ 25 Enhancer enhancer = new Enhancer(); 26 enhancer.setSuperclass(target.getClass()); 27 enhancer.setCallback(this); 28 return enhancer.create();//创建代理对象并返回 29 } 30 31 32 public void before() 33 { 34 System.out.println("婚礼正在紧张筹备中,请耐心等待。。。"); 35 36 } 37 38 39 public void after() 40 { 41 42 System.out.println("恭喜你进入人生第二阶段。。。。"); 43 } 44 45 46 @Override 47 public Object intercept(Object arg0, Method arg1, Object[] arg2, 48 MethodProxy arg3) throws Throwable { 49 before(); 50 Object result = arg3.invokeSuper(arg0, arg2); 51 after(); 52 return result; 53 } 54 55 }
1 package com.wisezone.test; 2 3 /** 4 * 测试类 5 * @author 王东海 6 * @2017年4月29日 7 */ 8 public class TestCglibProxy { 9 public static void main(String[] args) { 10 CglibInterceptor cglibInterceptor = new CglibInterceptor(new You()); 11 You you = (You) cglibInterceptor.getProxy(); 12 you.toMarry(); 13 } 14 }
结果: