Spring中Aop的理解

Spring中的Aop

1、什么是AOP?

面向切面编程。利用它可以对业务逻辑的各个部分进行隔离,从而使得业务部分之间的耦合度降低,提高程序开发效率。

应用场景有:日志记录、性能统计、安全控制、事务处理、异常处理...

 

通俗描述:不通过修改源代码方式,在主干功能里添加新功能

 

AOP底层原理:

1、底层使用了动态代理

(1)有两种情况的动态代理

第一种:有接口,使用JDK动态代理

(1)调用newProxyInstance方法

方法三个参数:

第一:类加载器

第二:增强方法所在的类,这个类实现的接口,支持多个接口

第三:实现这个接口InvocationHandler,创建代理对象,写增强方法,示例代码如下:

public class ProxyJDK {
    public static void main(String[] args) {
        //创建接口实现类代理对象
        Class[] interfaces = {UserDao.class};
     /*   Proxy.newProxyInstance(ProxyJDK.class.getClassLoader(), interfaces, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return null;
            }
        });*/
        UserDaoImpl userDao=new UserDaoImpl();
        UserDao dao = (UserDao) Proxy.newProxyInstance(ProxyJDK.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
        dao.update();
    }
}


//创建代理对象代码
class UserDaoProxy implements InvocationHandler {
    //创建的是谁的代理对象,把谁传过来,有参构造器
    private Object obj;

    public UserDaoProxy(Object obj) {
        this.obj = obj;
    }

    //增强部分
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法之前
        System.out.println("开始增强" + method.getName() + ":传递的参数.." + Arrays.toString(args));
        //被增强的方法执行
        Object invoke = method.invoke(obj, args);
        //方法之后
        System.out.println("执行结束" + obj);

        return null;
    }
}

 

创建接口实现类代理对象,增强类的方法

 

第二种:没有接口情况,使用CGLIB动态代理

 

创建子类的代理对象,增强类的方法

 

AOP术语:

1、连接点:类里哪些方法可以被增强,这些方法称为切入点

 

2、切入点:实际被真正增强的方法

 

3、通知(增强):实际增强的逻辑部分

类型有:

前置通知:

后置通知:

环绕通知:

异常通知:

最终通知:

 

4、切面:是动作,把通知应用到切入点的过程

 

AOP操作:

1、一般基于AspectJ实现。

2、基于AspectJ实现AOP操作:

(1)基于xml配置文件

(2)基于注解方式(常用)

3、需要引入的依赖:

 

 其中aspectj.weaver包用下面的包代替:

 <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.7</version>
    </dependency>

  

 4、切入点表达式:

(1)作用:知道对哪个类里的哪个方法进行增强

(2):语法结构:

execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))

示例:对com.zhaojianhui.dao.Bookdao类里的add方法增强

execution(* com.zhaojianhui.dao.Bookdao.add(..))

示例:对com.zhaojianhui.dao.Bookdao类里的所有方法增强

execution(* com.zhaojianhui.dao.Bookdao.*(..))

示例:对com.zhaojianhui.dao包里所有类,类里的所有方法增强

execution(* com.zhaojianhui.dao.*.*(..))

AOP操作(注解方式)

1、创建类,在类中定义方法

public class User {
    public void add(){
        System.out.println("add...");
    }
}

  2、创建增强类(编写增强逻辑)

//增强类
public class UserProxy {
    //前置通知
    public void before(){
        System.out.println("before..");
    }
}

  3、通知配置

(1)在spring配置文件中开启注解扫描

<?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:util="http://www.springframework.org/schema/util"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/util
         http://www.springframework.org/schema/util/spring-util.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">

  

(2)使用注解创建User和UserProxy对象

(3)在增强类上加注解@Aspect

(4)在spring配置文件中开启生成代理对象

 <!--开启AspectJ代理生产对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

  4、配置不同类型通知

@Component
@Aspect
//增强类
public class UserProxy {
    //前置通知
    @Before("execution(* org.zhaojianhui.Spring.Bean.User.add(..))")
    public void before(){
        System.out.println("before..");
    }
}

测试:

public void test() {
        ApplicationContext appo = new ClassPathXmlApplicationContext("bean2.xml");
        //ApplicationContext appo = new AnnotationConfigApplicationContext(SpringConfig.class);;//加载配置类
        User user = appo.getBean("user", User.class);
        user.add();


    }
}

  

public class ProxyJDK {
public static void main(String[] args) {
//创建接口实现类代理对象
Class[] interfaces = {UserDao.class};
/* Proxy.newProxyInstance(ProxyJDK.class.getClassLoader(), interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
});*/
UserDaoImpl userDao=new UserDaoImpl();
UserDao dao = (UserDao) Proxy.newProxyInstance(ProxyJDK.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
dao.update();
}
}


//创建代理对象代码
class UserDaoProxy implements InvocationHandler {
//创建的是谁的代理对象,把谁传过来,有参构造器
private Object obj;

public UserDaoProxy(Object obj) {
this.obj = obj;
}

//增强部分
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法之前
System.out.println("开始增强" + method.getName() + ":传递的参数.." + Arrays.toString(args));
//被增强的方法执行
Object invoke = method.invoke(obj, args);
//方法之后
System.out.println("执行结束" + obj);

return null;
}
}


相同切入点抽取:
//前置通知
    @Before(value = "pointCutDemo()")
    public void before() {
        System.out.println("before..");
    }
    //相同切入点抽取
    @Pointcut(value = "execution(* org.zhaojianhui.Spring.Bean.User.add(..))")
    public void pointCutDemo() {

    }

有多个增强类对同一个方法进行增强,设置增强类优先级:在增强类上添加@Order(值)注解,值越小,优先级越高。



原文地址:https://www.cnblogs.com/zhaojianhui/p/13467393.html