【Spring】Aop

AOP

概念

面向切面编程:对业务的各个部分进行隔离,减低耦合度,提高程序的可重用性,同时提高效率。

解析

以登录功能为例:

如果增加功能,不通过修改源代码的方式,降低耦合度。

底层原理

AOP底层使用的是 动态代理

  1. 有两种情况

    1. 有接口的情况

      使用JDK的动态代理

    2. 没有接口的情况

      使用CGLIB的动态代理

代理

还是按照登录为例子

public interface Dao
{
    void login(){}
}

如果我们需要在登录中添加新的逻辑,使用AOP的话就是创建一个这个接口的实现对象的代理对象。


如果没有接口,例如

public class User{
    public void login(){}
}

如果想要在上面添加一些逻辑,增强login方法,可以继承User类,在子类中调用父类的方法,并且添加额外的逻辑。

而此时的动态代理(CGLIB),那么创建当前类的子类的代理对象。
注意,动态代理增强的都是接口中的方法,并不适用于普通方法。

public class JdkProxy {

  public static void main(String[] args) {
    Class[] interfaces = {UserDao.class};
    UserDao us = new UserDaoImpl();
    UserDao userDao =(UserDao) Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), interfaces,
        new UserDaoProxy(us));
    userDao.update();
  }

  static class UserDaoProxy implements InvocationHandler {

    private Object object;

    public UserDaoProxy(Object userDao) {
      this.object = userDao;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      System.out.println("方法之前执行" + method.getName());
      Object invoke = method.invoke(object, args);
      System.out.println("方法之后执行" + object);
      return invoke;
    }
  }
}

AOP术语

  1. 连接点:类中的哪些方法可以(enable)被增强, 这些方法就被称为连接点。

  2. 切入点:实际真正被增强的方法称为切入点。

  3. 通知(增强):实际增强的逻辑部分称为通知。具有多种类型

    1. 前置通知:前面有
    2. 后置通知:后面有
    3. 环绕通知:前后都有
    4. 异常通知:异常才用
    5. 最终通知:类似于 finally
  4. 切面:把通知应用到切入点的过程就称为切面。

AspectJ

我们通常使用AspectJ来实现 AOP 的操作。

在xml中配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop.xsd">
  <context:component-scan base-package="service,dao,aop">

  </context:component-scan>

  <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

被代理类

@Component
public class User {

  public void add() {
    System.out.println("添加");
  }
}

代理类

@Component
@Aspect
public class UserProxy {

  //抽取公共切入点
  //..代表参数列表,。之类是包名.Class.Method(..) 的格式
  @Pointcut(value = "execution(* aop.User.add(..))")
  public void point() {

  }

  @Before("point()")
  public void before() {
    System.out.println("增强之前");
  }
  @Before("point()")
  public void after() {
    System.out.println("之后");
  }
}

测试

public class Test {

  public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
      //尽管我们使用的是注解,我们依然可以靠这样获取对象。
    User user = context.getBean("user", User.class);
    user.add();
  }
}

如果有多个增强类,可以设置这些增强类的优先级。

添加注解 order 里面的值越小,优先级越高。

完全注解开发

首先需要一个配置类。

@Configuration
@ComponentScan(basePackages = {"com.tifa.aop"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {

}

测试

public class Test {

  public static void main(String[] args) {
      //注意对象变了。
    ApplicationContext context = new AnnotationConfigApplicationContext(ConfigAop.class);
    var user = context.getBean( User.class);
    user.add("你");
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值