AOP——面向切面编程

用到的注解

@Component

  • @Component是Spring框架中的核心注解之一,它用于标识一个类为Spring容器的一个组件
  • 使得该类可以被Spring自动扫描并纳入管理。
  • 在使用@Component注解时,可以指定该组件的名称,也可以让Spring自动生成一个默认名称。 默认名称是首字母是小写的类名(如: Book 则id就是book)
  • 每个组件都会被当作一个Bean对象,被纳入到Spring容器中进行管理。

@ComponentScan(basePackages={“com.hyp.Spring.Aspect”})

  • 组件查找 用于指示Spring容器应该扫描那些包以查找组件

@EnableAspectJAutoProxy(proxyTargetClass = true)

  • @EnableAspectJAutoProxy是Spring框架中的注解,用于开启基于AspectJ的切面自动代理。
  • 通过在配置类上添加@EnableAspectJAutoProxy注解, 可以使得Spring框架自动为被@Aspect注解所标记的切面类创建代理对象,并将这些代理对象添加到Spring容器中供其他组件使用。
  • @EnableAspectJAutoProxy注解支持一个名为proxyTargetClass的属性,用于指定切面代理的类型。
  • 当该属性值为true时,代理对象基于类进行创建;当该属性值为false时,代理对象基于接口进行创建。默认情况下,该属性值为false

@Order(1)

  • 用于指定Bean对象在同一类型的多个Bean对象中的加载顺序
  • 数值越小的Bean对象将会越早被加载

@Acpect

  • 声明这是一个切面类,并创建这个类的代理对象,交给Spring容器
  • 使用此注解需要在配置文件中配置
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

注意: 即使没有配置上述代码,方法也可以实现增强是为什么呢?

这是因为:
当 <aop:aspectj-autoproxy> 元素缺失时,
默认启用的是基于代理的 AOP,因此即使没有显式地配置 <aop:aspectj-autoproxy>,
仍然可以实现增强。但是如果你使用的是 AspectJ 特定的语法,
如 @DeclareParents 和 @DeclareErrorRendering 等,
则必须使用 <aop:aspectj-autoproxy> 启用 AspectJ 模式。

因此,建议在使用 @Aspect 注解的同时,显式地在 Spring 配置文件中配置 < aop:aspectj-autoproxy> 元素以启用 AOP 功能。

使用AOP

在使用AOP时,有两种方式

  1. xml配置文件配置【bean.xml】
  2. 完全注解开发【Annotation(注解)】

使用配置文件开发

使用xml文件配置增强类(不使用注解)

AcpectJ.xml:
使用xml配置文件进行配置时,需要创建被增强类和增强类的bean对象
并且需要配置aop


  <!--先创建增q类和被增强类的bean对象-->
    <!--被增强类-->
    <bean id="user" class="com.hyp.Spring.Aspect.User.User"></bean>
    <!--增强类-->
    <bean id="userProxy" class="com.hyp.Spring.Aspect.User.UserProxy"></bean>

    <!--配置aop增强-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="cut" expression="execution(* com.hyp.Spring.Aspect.User.User.say(..))"/>
        <!--配置切面 使用的是前置通知   -->
        <aop:aspect ref="userProxy">
            <aop:before method="before" pointcut-ref="cut"></aop:before>
        </aop:aspect>
    </aop:config>

Java代码

测试代码

/**
 * 被增强类
 */
public class User{
    /*切点*/
    public void say() {
        System.out.println("人说话~~");
    }
}
/**
 * 增强类
 */
public class UserProxy {
    /*通知*/
    public void before(){
        System.out.println("前置通知");
    }
}
/**
测试类
**/
public class textAop{
 @Test
    public void testBeforeByConfigFile(){
        ApplicationContext context = new ClassPathXmlApplicationContext("AspectJ.xml");
        //使用getBean()方法获取User对象,
        User user = context.getBean("user",User.class);
        user.say();
    }
}

测试结果

使用xml配置文件的运行结果

使用注解开发

bean.xml
需要在bean.xml文件中打开注解扫描,并且开启Aspect自动生成代理对象

<!--开启组件扫描  使用注解时使用
	base-package属性是定义在某个包之下开启注解扫描-->
    <context:component-scan base-package="com.hyp.Spring.Aspect"></context:component-scan>
<!--开启Aspect生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  • 这段XML代码是使用Spring AOP时开启Aspect生成代理对象的配置。它使用了aop:aspectj-autoproxy标签,指示Spring启用AspectJ的自动代理功能。在类上加注@Acpect注解,并在xml文件中开启Acpect生成代理对象。
  • 在Spring AOP中,开启自动代理(autoproxy)可以让Spring根据切点表达式自动生成代理对象,并在方法调用前、后或抛出异常时织入相应的增强处理逻辑,从而实现横切关注点的功能。
  • 如果不开启自动代理,则需要手动配置每个切面,并将其作为bean添加到Spring应用程序上下文中。使用自动代理更加方便和灵活,可以简化Spring应用程序中AOP的配置和管理。

bean.xml

需要在bean.xml文件中打开注解扫描

 <!--开启组件扫描  使用注解时使用-->
    <context:component-scan base-package="com.hyp.Spring.Aspect"></context:component-scan>
    

增强类

@Component//创建增强类对象 用于标识一个类为Spring容器的一个组件,使得该类可以被Spring自动扫描并纳入管理
@Aspect //声明这是一个切面类,并创建这个类的代理对象,交给Spring容器
@Order(2)//设置增强类的优先级
public class BookProxy {

    /**
     * 切入点方法
     */
    /*给一个切入点增强多个功能时,每一个都要指定切入点,每个个都要写切入点表达式
    相 当繁琐可以使用@Pointcut注解,进行相同切入点的抽取*/
    @Pointcut(value = "execution(* com.hyp.Spring.Aspect.Book.addBook(..))")
    public void pointCut() {

    }
    /**
     * 使用Before注解
     * 设置方法的前置通知
     * 使用切面表达式("execution=(* com.hyp.Spring.Aspect.Book.addBook(.))")
     * 设置这个前置通知的 切点
     */
    @Before(value = "execution(* com.hyp.Spring.Aspect.Book.addBook(..))")
    //使用相同切入点函数(必须抽取相同切入点)
    public void before() {
        System.out.println("前置通知");
    }

    /*
     最终通知,
     不论程序怎么样执行都会执行
     使用切入点方法pointCut()
     */
    @After(value = "pointCut()")
    public void after() {
        System.out.println("最终通知");
    }

    /*遇到异常的话,不会执行*/
    @AfterReturning(value = "execution(* com.hyp.Spring.Aspect.Book.addBook(..))")
    public void AfterReturning() {
        System.out.println("afterRetuning,后置通知(也被称为返回通知)");
    }

    /*异常通知,程序出现异常的话,执行
     * 没有异常,不执行*/
    @AfterThrowing(value = "execution(* com.hyp.Spring.Aspect.Book.addBook(..))")
    public void afterThrowing() {
        System.out.println("afterThrowing 异常通知");
    }

    /*环绕通知,*/
    @Around(value = "execution(* com.hyp.Spring.Aspect.Book.addBook(..))")
    public void Around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕通知前");
        point.proceed();
        System.out.println("环绕通知后");
    }
}

测试类:

 @Test
    public void testBookProxy(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //因为Book对象使用了@Component注解,
        // Spring容器自动为这个类创建了一个bean对象,将id自动设置为首字母为小写的类名
        //getBean(String id , Class class) ,id 是bean对象的id
        Book book = context.getBean("book", Book.class);
        book.addBook("java核心技术");
    }

被增强类

/**
 * 被增强类Book
 * 因为Book对象使用了@Component注解,Spring容器自动为这个类创建了一个bean对象,
 * 将id自动设置为首字母为小写的类名
 * 供使用getBean(String id , Class class)方法使用
 **/
@Component//创建被增强类对象
public class Book {
    public void addBook(String name) {
        /*int i = 1/0;*///异常通知测试用例
        System.out.println("添加书本" + name);
    }

    public void update(Book book) {
        System.out.println("修改书本对象" + book);
    }
}

运行结果

在这里插入图片描述

完全注解开发

使用完全注解开发,需要使用到配置类(configClass),配置类代替xml文件进行Spring的配置

@Configuration

标记这个类为一个配置类,相当于一个创建一个xml文件

@ComponenScan(basePackages={“com.hyp.Sping.Adpect”})

组件查找,用于指示Spring容器应该扫描那些包以查找组件,开启注解扫描的作用
和配置文件xml中 <context:component-scan base-package="com.hyp.Spring.Aspect"></context:component-scan>作用相同

@EnableAspectJAutoProxy(proxyTargetClass = true)

开启切面自动代理
proxyTargetClass当该属性值为true时,代理对象基于类进行创建; 当该属性值为false时,代理对象基于接口进行创建
相当于xml文件中<aop:aspectj-autoproxy></aop:aspectj-autoproxy>的作用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值