Spring_AOP
切面(aspect)
将横切多个业务对象的程序独立出来模块化,改模块可以无侵入式的集成到业务对象中,例如:事务、日志、权限
通知(advice)
通知是指切面的具体实现,如记录日志,权限验证
通知有各种类型,其中包括:before、 after 、around和throw等通知
连接点(joinPoint)
通知执行的时机,如方法调用时,抛出异常等
切入点(PointCut)
切入点是感兴趣的连接点,通知和一个切入点表达式关联,并在满足这个切入点的链接点上运行,例如:当执行某个特定的名称方法
切入点表达式如何和链接点匹配是AOP的核心:spring缺省使用AspectJ切入点语法。
目标(Target)
被一个或者多个切面所通知的对象,也有人把它叫做被通知对象,也可以是一个被代理的对象。
AOP代理(AOP proxy)
AOP框架创建的对象,用来实现切面的功能。在Spring中,AOP代理可以是JDK动态代理也可以是CGLIB代理。Spring 2.0最新引入的基于模式(schema-based)风格和@AspectJ注解风格的切面声明,对于使用这些风格的用户来说,代理的创建是透明的。
织入(Weaving)
把切面链接到其他应用程序类型或者对象上,并创建一个被通知的对象。Spring和其他纯Java AOP框架一样,在运行时完成织入。
静态代理
将系统中与业务逻辑无关的业务,由代理来完成。
动态代理:
在静态代理中,代理对象和被代理对象必须实现同一个接口。静态代理的弊端,一个代理接口只服务与一种类型的对象,系统庞大的时候代理会很多。
动态代理:使用动态代理可以实现java中的java.lang.reflect.InvocationHandler接口(反射机制)
该接口中的一个方法是:
public Object invoke(Object proxy,Method method,Objrct[] args)
proxy:代理对象
method:代理管理方法
args:方法的参数
举例:打印日志的动态代理
创建UserDao接口
1 package com.feimao.proxy.test; 2 3 public interface UserDao { 4 public void delete(String name); 5 }
创建UserDao接口的实现类
1 package com.feimao.proxy.test; 2 3 import java.util.logging.Level; 4 import java.util.logging.Logger; 5 6 public class UserDaoImpl implements UserDao { 7 //Logger logger = Logger.getLogger(this.getClass().getName()); 8 @Override 9 public void delete(String name) { 10 //logger.log(Level.INFO , "before delete"); 11 System.out.println("删除成功!"); 12 //logger.log(Level.INFO , "after delete"); 13 } 14 15 }
创建动态代理类
1 package com.feimao.proxy.test; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 import java.util.logging.Level; 7 import java.util.logging.Logger; 8 9 public class DynamicLogProxy implements InvocationHandler{ 10 Object delegate;//Object是指代理所有对象,固定的类型只能代理一个 11 Logger logger = Logger.getLogger(this.getClass().getName()); 12 public Object bind(Object delegate){ 13 this.delegate = delegate; 14 Class cls = delegate.getClass(); 15 return Proxy.newProxyInstance(cls.getClassLoader() , cls.getInterfaces() , this); 16 } 17 public Object invoke(Object proxy , Method method , Object[] args) 18 throws Throwable{ 19 logger.log(Level.INFO , "before delete"); 20 System.out.println(args[0]); 21 Object retvalue = method.invoke(delegate , args); 22 logger.log(Level.INFO , "after delete"); 23 return retvalue; 24 } 25 }
创建测试类
1 package com.feimao.proxy.test; 2 3 public class Test { 4 public static void main(String[] args){ 5 /* UserDao dao = new UserDaoImpl(); 6 dao.delete("feimao");*/ 7 UserDao dao = (UserDao) new DynamicLogProxy().bind(new UserDaoImpl());//强制类型转换 8 dao.delete("feimao"); 9 } 10 }
运行结果:
接下来我们再来代理下其他类,比如:代理顾客类
创建CustomerDao接口
1 package com.feimao.proxy.test; 2 3 public interface CustomerDao { 4 public String del(String name); 5 6 }
创建CustomerDaoImpl接口的实现类
1 package com.feimao.proxy.test; 2 3 public class CustomerDaoImpl implements CustomerDao { 4 @Override 5 public String del(String name) { 6 System.out.println("delete ok …"); 7 return "zhubaobao"; 8 } 9 }
创建测试类
1 package com.feimao.proxy.test; 2 3 public class Test { 4 public static void main(String[] args){ 5 /* UserDao dao = new UserDaoImpl(); 6 dao.delete("feimao");*/ 7 CustomerDao dao = (CustomerDao) new DynamicLogProxy().bind(new CustomerDaoImpl());//强制类型转换 8 String str = dao.del("feimao"); 9 System.out.println(str); 10 } 11 }
结果如下: