博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring AOP-----------基础
阅读量:4947 次
发布时间:2019-06-11

本文共 14354 字,大约阅读时间需要 47 分钟。

AOP概述

  1、AOP术语

    连接点:连接点好比一个类的方法,每一个方法都是一个连接点

    切点:每个方法有大量的逻辑构成,可以将任何一个位置作为执行点,这个执行点作为切点。

    增强:就是嵌入方法中的一段逻辑。

    目标对象:织入增强的目标类。

    引介:特殊的增强,为类加入方法和属性。

    织入:将增强嵌入切点的过程。

    代理:织入增强后产生的结果类。

    切面:切入点+增强

创建增强类

  前置增强

    前置增强=连接点前+增强,增强只是针对所有的的连接点。前置增强的实现类为MethodBeforeAdvice

    前置增强的过程:1、创建代理工厂;2、创建目标类,也就是需要织入增强的类;3、通过MethodBeforeAdvice生成增强类;4、将增强类和目标类添加到代理工厂;5、生成目标代理。

    实例:      

    创建目标类

package advice;public interface Waiter {	void greetTo(String name);	void serverTo(String name);}

  

package advice;public class NaiveWaiter implements Waiter {	@Override	public void greetTo(String name) {		// TODO Auto-generated method stub		System.out.println("greet to"+name+"......");	}	@Override	public void serverTo(String name) {		// TODO Auto-generated method stub		System.out.println("serving "+name+"......");	}}

    创建前置增强

package advice;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;public class GreetingBeforeAdvice implements MethodBeforeAdvice{	@Override	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {		// TODO Auto-generated method stub		//arg0标识目标方法,arg1标识目标方法的参数值,arg2标识目标实例		System.out.println("====="+arg0.getName()+"=====");		String clientName = (String) arg1[0];		System.out.println("How are you!"+clientName+".");		System.out.println("===="+arg2.getClass().getName()+"====");	}}

   设置前置增强

package advice;import org.springframework.aop.framework.ProxyFactory;public class TestBeforeAdvice {	public static void main(String[] args){		//创建目标实例		NaiveWaiter waiter = new NaiveWaiter();		//创建增强实例		GreetingBeforeAdvice advice = new GreetingBeforeAdvice();		//创建代理工厂		ProxyFactory factory = new ProxyFactory();		//设置代理目标		factory.setTarget(waiter);		//为代理类添加增强		factory.addAdvice(advice);		//生成代理实例		Waiter proxy = (Waiter) factory.getProxy();		proxy.greetTo("JSON");		proxy.serverTo("JSON");	}}

  Spring配置前置增强实例:

    application配置

    设置前置增强

package beforeadvice;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestSpringBefore {	public static void main(String[] args){		String path = "application.xml";		ApplicationContext ap = new ClassPathXmlApplicationContext(path);		Waiter waiter = (Waiter) ap.getBean("waiter");		waiter.greetTo("JACK");		waiter.serverTo("JACK");	}}

  后置增强

    后置增强=连接点后+增强,后置增强是将在方法后织入增强,后置增强的实现类为AfterReturningAdvice

    前置增强的过程:1、创建代理工厂;2、创建目标类,也就是需要织入增强的类;3、通过AfterReturningAdvice生成增强类;4、将增强类和目标类添加到代理工厂;5、生成目标代理。

    实例:

     创建后置增强类

package advice.after;import java.lang.reflect.Method;import org.springframework.aop.AfterReturningAdvice;public class GreetingAfterAdvice implements AfterReturningAdvice {	@Override	public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {		// TODO Auto-generated method stub		System.out.println("please enjoy yourself!");	}}

    设置后置增强

package advice.after;import org.springframework.aop.framework.ProxyFactory;import com.sun.org.glassfish.external.statistics.Statistic;import advice.before.GreetingBeforeAdvice;import advice.before.NaiveWaiter;import advice.before.Waiter;public class TestAfterAdvice {	public static void main(String[] args){		//创建目标实例		NaiveWaiter waiter = new NaiveWaiter();		//创建增强实例		GreetingAfterAdvice advice = new GreetingAfterAdvice();		//创建代理工厂		ProxyFactory factory = new ProxyFactory();		//设置代理目标		factory.setTarget(waiter);		//为代理类添加增强		factory.addAdvice(advice);		//生成代理实例		Waiter proxy = (Waiter) factory.getProxy();		proxy.greetTo("JSON");		proxy.serverTo("JSON");	}}

   Spring配置后置增强实例:

    application配置 

greetingBeforeAdvice
after

    设置后置增强

package advice.before;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestSpringBefore {	public static void main(String[] args){		String path = "application.xml";		ApplicationContext ap = new ClassPathXmlApplicationContext(path);		Waiter waiter = (Waiter) ap.getBean("waiter");		waiter.greetTo("JACK");		waiter.serverTo("JACK");	}}

 环绕增强

    环绕增强=连接点前后+增强,在方法的前后都会织入增强,环绕增强的实现类为MethodInterceptor。

    环绕增强过程:1、创建代理工厂;2、创建目标类,也就是需要织入增强的类;3、通过AfterReturningAdvice生成增强类;4、将增强类和目标类添加到代理工厂;5、生成目标代理。 

    Spring配置环绕增强实例:

    定义增强类

package advice.interceptor;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.springframework.stereotype.Component;@Component("interceptor")public class GreetingInterceptor implements MethodInterceptor{	@Override	public Object invoke(MethodInvocation arg0) throws Throwable {		// TODO Auto-generated method stub		//目标方法入参		Object[] args = arg0.getArguments();		String str = (String) args[0];		System.out.println(str+"先生,你好!");		//执行目标方法		Object object = arg0.proceed();		System.out.println(str+"先生,有什么帮忙的?");		return object;	}}

    设置Spring配置

greetingBeforeAdvice
after
interceptor

    设置环绕增强

package advice.before;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestSpringBefore {	public static void main(String[] args){		String path = "application.xml";		ApplicationContext ap = new ClassPathXmlApplicationContext(path);		Waiter waiter = (Waiter) ap.getBean("waiter");		waiter.greetTo("JACK");		waiter.serverTo("JACK");	}}

  异常抛出增强   

    异常抛出增强=连接点异常后+增强,在异常后会织入增强,异常抛出增强的实现类为ThrowsAdvice。

    异常抛出增强过程:1、创建代理工厂;2、创建目标类,也就是需要织入增强的类;3、通过ThrowsAdvice生成增强类;4、将增强类和目标类添加到代理工厂;5、生成目标代理。

    Spring配置异常增强实例:

     创建目标类

package advice.throwsadvice;import java.sql.SQLException;import org.springframework.stereotype.Component;@Componentpublic class ForumService {	public void removeForum(){		throw new RuntimeException("运行异常.........");	}		public void updateForum() throws SQLException{		throw new SQLException("数据库更新异常..........");	}}

    创建异常增强类

package advice.throwsadvice;import java.lang.reflect.Method;import java.sql.SQLException;import java.util.concurrent.Executor;import org.springframework.aop.ThrowsAdvice;import org.springframework.stereotype.Component;@Componentpublic class TransactionThrows implements ThrowsAdvice{	public void afterThrowing(Method method,Object[] objects, 			Object target, RuntimeException exception){		System.out.println("操作报错========"+"RuntimeException");	}		public void afterThrowing(Method method,Object[] objects, 			Object target, SQLException exception){		System.out.println("操作报错========"+"SQLException");	}}

  Spring配置异常增强

transactionThrows

  引介增强

   引介增强只是对目标类添加属性和方法。

创建切面

    增强只是对每个类中的所有方法都要织入,没有条件限制。切面可以定位到目标类和目标方法进行增强的织入。

   切点类型

      • 静态方法切点:StaticMethodMatcherPointcut类过滤接入点的类和方法。
      • 动态方法切点:DynamicMethodMatcherPointcut类在每次运行程序时都要过滤接入点的类和方法。
      • 注解切点
      • 表达式切点
      • 流程切点
      • 复合切点

   切面类型

      • Advisor:代表一般切面。
      • PoincutAdvisor:代表具有切入点的切面。
      • IntroductionAdvisor:代表引介切面。

   PointcutAdvisor

    PointcutAdvisor共有6个具体实现类

    • DefaultPointcutAdvisor:主要通过Pointcut和Advice构成一个切面,例如动态切面、流程切面、复合切面等切面的构成。
    • StaticMethodMatcherPointcutAdvisor:用于设置静态切面
    • NameMethodMatcherPointcutAdvisor:按照方法名定义切点的切面。
    • RegexMethodMatcherPointcutAdvisor:通过正则表达式匹配方法名定义切点的切面。
    • AspectJExpressionPointcutAdvisor
    • AspectJPointcutAdvisor

    1、静态普通方法名匹配切面

    该切面会通过类名和方法名对增强进行准确的织入。StaticMethodMatcherPointcutAdvisor方法对目标类和方法进行过滤。

    创建过程:1、创建目标类和方法;2、通过StaticMethodMatcherPointcutAdvisor创建切面对接入点进行过滤;3、创建增强;4、将增强注入切面;5、将目标类、切面加入代理。

    Waiter.java文件

package advisor;import org.springframework.stereotype.Component;@Component("waiterTarget")public class Waiter {	public void greetTo(String name){		System.out.println("waiter greet to "+name+"......");	}		public void serveTo(String name){		System.out.println("waiter serving to "+name+".....");	}}

    Seller.java文件

package advisor;import org.springframework.stereotype.Component;@Component("sellerTarget")public class Seller {	public void greetTo(String name){		System.out.println("seller greet to "+name+"......");	}		public void serveTo(String name){		System.out.println("seller serving to "+name+".....");	}}

  创建增强类

package advice.before;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;import org.springframework.stereotype.Component;@Componentpublic class GreetingBeforeAdvice implements MethodBeforeAdvice{	@Override	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {		// TODO Auto-generated method stub		//arg0标识目标方法,arg1标识目标方法的参数值,arg2标识目标实例		System.out.println("====="+arg0.getName()+"=====");		String clientName = (String) arg1[0];		System.out.println("How are you!"+clientName+".");		System.out.println("===="+arg2.getClass().getName()+"====");	}}

  创建切面

package advisor.staticmethod;import java.lang.reflect.Method;import org.springframework.aop.ClassFilter;import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;import advisor.Waiter;public class GreetingAdvisor extends StaticMethodMatcherPointcutAdvisor{	@Override	public boolean matches(Method method, Class
arg1) { // TODO Auto-generated method stub System.out.println("开始过滤方法======="); return "greetTo".equals(method.getName()); } @Override public ClassFilter getClassFilter(){ return new ClassFilter() { public boolean matches(Class clazz) { // TODO Auto-generated method stub System.out.println("开始过滤类======="); return Waiter.class.isAssignableFrom(clazz); } }; }}

  Spring配置文件  

  测试

package advisor;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestAdvisor {	public static void main(String[] args){		String path = "application.xml";		ApplicationContext ap = new ClassPathXmlApplicationContext(path);		Waiter waiter =  (Waiter) ap.getBean("waiter1");		waiter.greetTo("李小龙");	}}

    2、静态正则表达式方法匹配切面 

    该切面会通过类名和方法名对增强进行准确的织入。RegexMethodMatcherPointcutAdvisor方法对目标类和方法进行过滤。

    创建过程:1、创建目标类和方法;2、通过RegexMethodMatcherPointcutAdvisor创建切面对接入点进行过滤;3、创建增强;4、将目标类、切面和增强加入代理。

    3、动态切面

     动态切点在每次执行时都要进行目标类和目标方法的检查,虽然这会对服务性能造成影响,因此在进行动态检查时,首先进行静态检查,检查通过后进行动态检查。动态切面使用的类为DynamicMethodMatcherPointcut

    创建过程:1、创建目标类和方法;2、通过DynamicMethodMatcherPointcut创建动态切面;3、创建增强;4、将增强和动态切面注入默认切面;5、将目标类、切面注入代理。

    创建动态切点类  

package advisor.dynamic;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;import org.springframework.aop.ClassFilter;import org.springframework.aop.support.DynamicMethodMatcherPointcut;import advisor.Waiter;public class GreetingDynamicPointcut extends DynamicMethodMatcherPointcut{	private static List
list = new ArrayList
(); static{ list.add("李小刚"); } public boolean matches(Method method, java.lang.Class
targetClass) { System.out.println("对方法进行静态过滤========="); return "serveTo".equals(method.getName()); } @Override public boolean matches(Method arg0, Class
arg1, Object... arg2) { // TODO Auto-generated method stub System.out.println("对方法进行动态过滤================="); String clientname = (String) arg2[0]; return list.contains(clientname); } public ClassFilter getClassFilter(){ System.out.println("对类进行过滤==============="); return new ClassFilter() { @Override public boolean matches(Class
arg0) { // TODO Auto-generated method stub return Waiter.class.isAssignableFrom(arg0); } }; }}

  Spring进行配置动态切面

  测试

package advisor;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestAdvisor {	public static void main(String[] args){		String path = "application.xml";		ApplicationContext ap = new ClassPathXmlApplicationContext(path);		Waiter waiter =  (Waiter) ap.getBean("waiter2");		waiter.serveTo("李小刚");			}}

    4、流程切面

    流程切面与动态切面相似,但是效率较低。流程切面主要有DefaultPointcutAdvisor和ControlFlowPointcut实现。

    创建过程:1、创建目标类和方法;2、创建增强;3、ControlFolwPointcut类注入目标类和方法生成切点;4、将切点和增强注入普通切面;5、将切面和目标方法注入代理;

    Spring文件配置

  需要织入增强的类

package advisor.controlfolw;import advisor.Waiter;public class WaiterDelegate {	private Waiter waiter;	public Waiter getWaiter() {		return waiter;	}	public void setWaiter(Waiter waiter) {		this.waiter = waiter;	}		public void service(String clientName){		waiter.greetTo(clientName);		waiter.serveTo(clientName);	}}

  测试

package advisor;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import advisor.controlfolw.WaiterDelegate;public class TestAdvisor {	public static void main(String[] args){		String path = "application.xml";		ApplicationContext ap = new ClassPathXmlApplicationContext(path);		Waiter waiter =  (Waiter) ap.getBean("waiter3");		WaiterDelegate delegate = new WaiterDelegate();		delegate.setWaiter(waiter);		delegate.service("小刚");			}}

    5、复合切点切面

     复合切点切面是将多个切点添加到复合切点对象中,生成复合切点的类为ComposablePointcut类。复合切点可以由两种方法实现,1、insertsection方法实现切点交集;2、union方法实现切点并集。

    创建过程:1、通过ComposablePointcut创建复合切点,将其他类型的切点加入其中。2、将复合切点和增强注入切面Bean中;3、将切面注入代理Bean。

    创建复合切点类

    

package advisor.composable;import org.springframework.aop.Pointcut;import org.springframework.aop.support.ComposablePointcut;import org.springframework.aop.support.ControlFlowPointcut;import org.springframework.aop.support.NameMatchMethodPointcut;import org.springframework.stereotype.Component;import advisor.controlfolw.WaiterDelegate;@Component("componsable")public class GreetingComposablePointcut {	public ComposablePointcut getComposablePointcut(){		ComposablePointcut pointcut = new ComposablePointcut();		Pointcut pc = new ControlFlowPointcut(WaiterDelegate.class, "service");		NameMatchMethodPointcut mPointcut = new NameMatchMethodPointcut();		mPointcut.addMethodName("greetTo");		return pointcut.intersection(pc).intersection(mPointcut);	}}

  Spring配置

 

转载于:https://www.cnblogs.com/youzhongmin/p/8519716.html

你可能感兴趣的文章
document操作例题2-下拉列表与选项卡
查看>>
c++子类继承父类的覆盖问题
查看>>
[转]Sublime text2安装php beautifier
查看>>
oppo手机权限开启方法3.1
查看>>
vs2013给项目统一配置boost库
查看>>
详解Linux操作系统的进程
查看>>
java网络编程客户端与服务端原理以及用URL解析HTTP协议
查看>>
Audio Policy 分析
查看>>
sublime 关闭打开时候弹出的更新
查看>>
MSChart
查看>>
uva 12097—— Pie
查看>>
TensorFlow——学习率衰减的使用方法
查看>>
nyoj28 大数阶乘 亿进制优化
查看>>
Python3 函数式编程
查看>>
jQuery合并单元格以及还原重置
查看>>
strip()函数和 split()函数
查看>>
PHP服务器脚本 PHP内核探索:新垃圾回收机制说明
查看>>
基于 QQBot 实现简易 QQ 机器人
查看>>
炫酷的时钟--canvas初体验
查看>>
1-3-07:计算多项式的值
查看>>