Spring框架——AOP

本文内容纲要:

- 代理模式

- 静态代理

- 实现

- 被代理对象

- 代理对象

- 使用

- 缺点:

- 动态代理

- 实现

- AOP (Aspect-Oriented Programmin) 面向切面编程

- 概念

- 通知类型

- AOP实现方式

- SpringAPI传统方式

- 前置通知 MethodBeforeAdvice接口

- 后置通知 AfterReturningAdvice接口

- 环绕通知 MethodInterceptor接口

- 异常通知 ThrowsAdvice接口

- xml配置代理模式

- 使用

- 纯POJO类-基于xml

- 通知类java

- xml配置

- 执行顺序

- 纯POJO类-基于注解驱动

- xml配置

- 注解配置

- 通知顺序

- 后置通知和最终通知的区别

- 使用AspectJ切面

- 每日英语

代理模式

代理模式创建代理对象,让代理对象控制目标对象的访问,并且可以在不改变目标对象的情况下添加一些额外的功能

不破坏原来代码的业务逻辑结构

静态代理

代理对象与被代理对象必须实现同一接口,在代理对象中实现日志

实现

  • 被代理对象

    public class UserServiceImpl implements UserService {

    public boolean login(String name, String password){

    if(name.equals("adi") && password.equals("123")){

    System.out.println("业务逻辑:用户adi登录成功");

    return true;

    }else{

    System.out.println("业务逻辑:用户adi登录失败");

    return false;

    }

    }

    }

  • 代理对象

    package staticproxy;

    import java.util.Date;

    public class UserServiceStaticProxy implements UserService {

    private UserService userService;

    public UserServiceStaticProxy(UserService userService) {

    this.userService = userService;

    }

    @Override

    public boolean login(String name, String password) {

    boolean isLogin = userService.login(name, password);

    System.out.println("日志:" + name + "于" + new Date().toLocaleString() + "登录");

    return isLogin;

    }

    }

  • 使用

    UserServiceStaticProxy proxy = new UserServiceStaticProxy(new UserServiceImpl());

    proxy.login("xxx","xxx");

缺点:

  1. 代理对象的一个接口只服务于一种类型的对象
  2. 如果要代理的方法很多,要为每种方法进行代理
  3. 静态代理在程序规模稍大时无法胜任

动态代理

  1. InvocationHandler接口,
  2. 操作代理对象时会执行invoke()方法,
  3. 使用Proxy.newProxyInstance()静态方法建立一个代理类对象(必须告知要代理的接口

实现

public class LoggerHandler implements InvocationHandler {

private Object delegate;

public Object bind(Object delegate) {

this.delegate = delegate;

return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this);

}

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

Object result = null;

System.out.println("方法名是:"+method.getName());

result = method.invoke(delegate, args);

System.out.println("日志:" + args[0] + "于" + new Date().toLocaleString() + "登录");

return result;

}

}

LoggerHandler lh = new LoggerHandler();

UserService us = (UserService) lh.bind(new UserServiceImpl());

us.login("adi", "123");

AOP (Aspect-Oriented Programmin) 面向切面编程

独立于Spring框架,但Spring实现了AOP。

  • 提供一种新的组织程序结构的思路
  • 对OOP补充,可OOP一起使用
  • OOP核心单位为类、AOP核心单位为切面

概念

  • 关注点:特定的问题、概念、或成需要达到的目标。
  • 横切关注点:一个关注点被多个类或者方法引用
  • 切面:一个切面是对一个横切关注点的模块化,(实现关注点的方法)
  • 连接点:程序执行过程中的某个点,方法调用或者抛出异常
  • 通知:在特定连接点应执行动作(定义何时)
  • 切入点:什么地方植入通知(何地
  • 目标对象:被切面所通知的对象(被代理的对象
  • 织入:将切面应用到目标对象,从而创建新的代理对象

通知类型

  • 前置通知(Before advice): 在某连接点之前执行的通知
  • 后置通知(After returning advice): 在某连接点正常完成后执行的通知
  • 异常通知(After throwing advice): 在方法抛出异常退出时执行的通知
  • 最终通知(After finally advice): 当某连接点退出的时候执行的通知
  • 环绕通知(Around advice): 包围一个连接点的通知,这是最强大的一种通知类型

AOP实现方式

SpringAPI传统方式

前置通知 MethodBeforeAdvice接口

public class Md5Advice implements MethodBeforeAdvice {

@Override

public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {

System.out.println(arg0.getName());

System.out.println(arg1[1]);

System.out.println(arg2.getClass().getName());

String newPwd = Md5Encode.getMD5(arg1[1].toString().getBytes());

arg1[1] = newPwd;

}

}

后置通知 AfterReturningAdvice接口

public class LogAdvice implements AfterReturningAdvice {

@Override

public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {

System.out.println(arg0);

System.out.println(arg3);

System.out.println(arg2[0]+"在"+new Date().toLocaleString()+"登录");

arg0=false;

}

}

环绕通知 MethodInterceptor接口

也可决定方法是否执行。

public class TimeAdvice implements MethodInterceptor {

@Override

public Object invoke(MethodInvocation arg0) throws Throwable {

System.out.println("方法开始执行时间:"+new Date().toLocaleString());

Object result = arg0.proceed();

System.out.println("方法结束执行时间:"+new Date().toLocaleString());

return result;

}

}

异常通知 ThrowsAdvice接口

public class RegistExceptionAdvice implements ThrowsAdvice {

public void afterThrowing(Exception e) {

System.out.println("异常通知发生异常"+e.getMessage());

}

}

xml配置代理模式

<!--注入代理的接口-->

<!--注入通知,list配置-->

<!--注入代理目标-->

<bean>

<bean id="UserProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

<property name="proxyInterfaces" value="com.user.UserService"></property>

<property name="interceptorNames">

<list>

<value>Md5Advice</value>

<value>TimeAdvice</value>

</list>

</property>

<property name="target" ref="UserServiceImpl"></property>

</bean>

</beans>

使用

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

//接口获取代理对象

UserService us = (UserService)ctx.getBean("UserProxy");

us.regist("adi", "123");

boolean bool = us.login("adi", "123");

System.out.println(bool);

纯POJO类-基于xml

  • 通知类java

  1. 方法名自己写

    public class MyAdvice {

    public void before(JoinPoint joinPoint) {

    System.out.println("前置通知");

    }

    //参数和配置名一致

    public void afterReturning(JoinPoint joinPoint, Object result) {

    System.out.println("后置通知");

    }

    public void after(JoinPoint joinPoint) {

    System.out.println("最终通知");

    }

    public Object around(ProceedingJoinPoint joinPoint) {

    System.out.println("环绕通知");

    Object[] args = joinPoint.getArgs();

    Object result = null;

    try {

    result = joinPoint.proceed(args);

    } catch (Throwable e) {

    e.printStackTrace();

    }

    System.out.println("环绕通知");

    return result;

    }

    public void throwMethod(Exception ex) {

    System.out.println("异常通知");

    }

    }

  • xml配置

    • 导入aop的命名空间
    • 配置bean元数据
    • 配置<aop:config>

    aop:config

    	<aop:aspect id="MyAspect" ref="MyAdvice" order="2">

    <aop:before method="before" pointcut="execution(* com.user.*.*(..))" />

    <aop:after-returning method="afterReturning" pointcut="execution(* com.user.*.*(..))" returning="result"/>

    <aop:around method="around" pointcut="execution(* com.user.*.*(..))" />

    <!--aop:after-throwing method="throwExMethod" pointcut="execution(* service.*.*(..))" throwing="ex"/-->

    <aop:after method="after" pointcut="execution(* com.user.*.*(..))" />

    </aop:aspect>

    </aop:config>

执行顺序

前置通知

环绕通知

业务执行....

最终通知

环绕通知

后置通知

纯POJO类-基于注解驱动

  • xml配置

    • aop自动代理
    • 注解配置

      <aop:aspectj-autoproxy />属性proxy-target-class

    • false ,jdk动态代理织入增强-代理模式
    • true,cglib动态代理织入增强-代理模式(不用加接口)

    <aop:aspectj-autoproxy />

    <context:annotation-config />

    <context:component-scan base-package="com" />

注解配置

  • 组件注解

  • 切面注解

  • 前置通知注解

  • 后置通知注解

  • 环绕通知注解

  • 最终通知注解

  • 异常通知注解

  • @Order(int)同类型通知排序(针对类),在类上加

    @Component

    @Aspect

    public class MyAdvice {

    // @Before("execution(* com.user..(..))")

    public void before(JoinPoint joinPoint) {

    System.out.println("前置通知");

    }

    // @AfterReturning(pointcut = "execution(* com.user.UserServiceImpl.*(..))", returning="result")

    public void afterReturning(JoinPoint joinPoint, Object result) {

    System.out.println("后置通知");

    }

    // @After("execution(* com.user..(..))")

    public void after(JoinPoint joinPoint) {

    System.out.println("最终通知");

    }

    @Around("execution(* com.user.*.*(..))")

    public Object around(ProceedingJoinPoint joinPoint) {

    System.out.println("环绕通知");

    Object[] args = joinPoint.getArgs();

    Object result = null;

    try {

    result = joinPoint.proceed(args);

    } catch (Throwable e) {

    e.printStackTrace();

    }

    System.out.println("环绕通知");

    return result;

    }

    // @AfterThrowing(value = "execution(* com.user..(..))", throwing="ex")

    public void throwMethod(Exception ex) {

    System.out.println("异常通知");

    }

    }

通知顺序

环绕通知

前置通知

业务执行,登录成功

环绕通知

最终通知

后置通知

后置通知和最终通知的区别

后置通知如果出现异常,无法返回数据时,后置通知无法执行,但是最终通知可以执行。

不管有没有异常,最终通知一定执行,

没有异常,返回值正常时,后置通知才执行。

使用AspectJ切面

  • 自己找素材看

每日英语

proxy 代理

Invocation 求助,调用

Handler 组织者、操作者

pointcut 切点

本文内容总结:代理模式,静态代理,实现,被代理对象,代理对象,使用,缺点:,动态代理,实现,AOP (Aspect-Oriented Programmin) 面向切面编程,概念,通知类型,AOP实现方式,SpringAPI传统方式,前置通知 MethodBeforeAdvice接口,后置通知 AfterReturningAdvice接口,环绕通知 MethodInterceptor接口,异常通知 ThrowsAdvice接口,xml配置代理模式,使用,纯POJO类-基于xml,通知类java,xml配置,执行顺序,纯POJO类-基于注解驱动,xml配置,注解配置,通知顺序,后置通知和最终通知的区别,使用AspectJ切面,每日英语,

原文链接:https://www.cnblogs.com/occlive/p/13558853.html

以上是 Spring框架——AOP 的全部内容, 来源链接: utcz.com/z/296674.html

回到顶部