Spring(二)AOP概念及其使用

AOP

1.什么是AOP

(1)AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码降低模块间的耦合度,并有利于未来的可拓展性和可维护性

2.AOP实现动态代理

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

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

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

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

创建当前类的子类的代理类,增强类的方法

3.(AOP) JDK动态代理

1)使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
    //第一参数,类加载器
    // 第二参数,增强方法所在的类,这个类实现的接口,支持多个接口
	// 第三参数,实现这个接口 InvocationHandler,创建代理对象,写增强的部分

2)编写 JDK 动态代理代码

1.创建接口,定义方法

public interface UserDao(){
    public int add(int a,int b);
    public String update(String id);
}

2.创建接口实现类,实现方法

public class UserDaoImpl implements UserDao{
 @Override
 public int add(int a, int b) {
 	return a+b;
 }
 @Override
 public String update(String id) {
 	return id;
 }
}

3.使用 Proxy 类创建接口代理对象

public class JDKProxy {
    public static void main(String[] args) {
        Class[] interfaces = {UserDao.class};
        UserDaoImpl userDao = new UserDaoImpl();
        UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new UserDaoProxy(userDao));
        int add = dao.add(3,3);
        System.out.println(add);
    }
}
//创建代理对象
class UserDaoProxy implements InvocationHandler{
    //1 把创建的是谁的代理对象,把谁传递过来
    //有参数构造传递
    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 res = method.invoke(obj, args);
        //方法之后
        System.out.println("方法之后执行...."+obj);
        return res;
    }
}

4.AOP相关术语

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

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

3.通知(增强):实际增强的逻辑部分称为通知,且分为以下五种类型:

前置通知 、后置通知 、环绕通知 、异常通知 、最终通知

4.切面:把通知应用到切入点过程

5.AOP操作

1.Spring 框架一般都是基于 AspectJ 实现 AOP 操作,AspectJ 不是 Spring 组成部分,独立 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使 用,进行 AOP 操作

2.基于 AspectJ 实现 AOP 操作:(1)基于 xml 配置文件实现 (2)基于注解方式实现(使用)

3.引入AOP相关的依赖

4.切入点表达式,如下:

1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强 
(2)语法结构: execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) )3)例子如下:
    例 1:对 com.atguigu.dao.BookDao 类里面的 add 进行增强
		execution(* com.atguigu.dao.BookDao.add(..))2:对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强
		execution(* com.atguigu.dao.BookDao.* (..))3:对 com.atguigu.dao 包里面所有类,类里面所有方法进行增强
		execution(* com.atguigu.dao.*.* (..))

6. 基于(AspectJ)注解的AOP操作

//1、创建类,在类里面定义方法
public class User {
public void add() {
System.out.println("add.......");
}
}
//2、创建增强类(编写增强逻辑)
//(1)在增强类里面,创建方法,让不同方法代表不同通知类型
//增强的类
public class UserProxy {
public void before() {//前置通知
System.out.println("before......");
}
}

进行通知的配置:

1.在spring配置文件中,开启注解扫描

2.使用注解创建相应的对象

3.在增强类上面添加注解@AspectJ

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


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/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>
    
    <aop:aspectj-autoproxy>aop:aspectj-autoproxy>
    
    
    
//增强的类
@Component
@Aspect  //生成代理对象
public class UserProxy {
     public void before() {//前置通知
 System.out.println("before......");
 }
}

//被增强的类
@Component
public class User {
     public void add() {
 System.out.println("add.......");
 }
}

配置不同类型的通知:

在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式

//4、配置不同类型的通知
@Component
@Aspect  //生成代理对象
public class UserProxy {
    //前置通知
    //@Before注解表示作为前置通知
    @Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void before() {
        System.out.println("before.........");
    }

    //后置通知(返回通知)有异常不执行
    @AfterReturning(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void afterReturning() {
        System.out.println("afterReturning.........");
    }

    //最终通知 不管有没有异常都执行
    @After(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void after() {
        System.out.println("after.........");
    }

    //异常通知
    @AfterThrowing(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void afterThrowing() {
        System.out.println("afterThrowing.........");
    }

    //环绕通知
    @Around(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕之前.........");

        //被增强的方法执行
        proceedingJoinPoint.proceed();

        System.out.println("环绕之后.........");
    }
}

对相同切入点抽取

//相同切入点抽取
    @Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void pointdemo() {

    }
    
 //前置通知
    //@Before注解表示作为前置通知
    @Before(value = "pointdemo()")//相同切入点抽取使用!
    public void before() {
        System.out.println("before.........");
    }

有多个增强类多同一个方法进行增强,设置增强类优先级

在增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高

@Component
@Aspect
@Order(1)
public class PersonProxy{ }

7.基于(AspectJ配置文件)进行AOP操作

1、创建两个类,增强类和被增强类,创建方法
2、在 spring 配置文件中创建两个类对象


<bean id="book" class="com.atguigu.spring5.aopxml.Book">bean>
<bean id="bookProxy" class="com.atguigu.spring5.aopxml.BookProxy">bean>


<aop:config>
 
 <aop:pointcut id="p" expression="execution(* com.atguigu.spring5.aopxml.Book.buy(..))"/>
 
 <aop:aspect ref="bookProxy">
 
 <aop:before method="before" pointcut-ref="p"/>
 aop:aspect>
aop:config>


8. 全注解开发

(1)创建配置类,不需要创建xml

@Congiguration
@ComponmentScan(basePack="{com.atguigu}")
@EnableAspectJAutoProxy(proxyTargetClas=true)
public class ConfigAop(){
    
}

你可能感兴趣的:(Spring)