Spring aop

发布于:2023-01-15 ⋅ 阅读:(489) ⋅ 点赞:(0)
  • 概念:

    • AOP指的是面向切面编程,利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。通俗点描述的话,就是:在不通过修改源代码的情况下,在主干功能里面添加新功能
  • 方式一:注解形式实现

一.新建maven项目,导入核心依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>demo</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>demo-aop1</artifactId>

    <dependencies>
        <!--讲aop,导这个包-->
        <!--Spring的AOP jar包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.19</version>
        </dependency>

        <!--如果需要使用@Aspect,导这个包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.3.19</version>
        </dependency>
    </dependencies>

</project>

二.新建UserDao和UserService的接口和实现类

package com.pro.dao;

public class UserDaoImpl implements UserDao {
    public void insert(String name) {
        System.out.println("-----"+name+",DaoImpl-------");

    }
}
package com.pro.service;

import com.pro.dao.UserDao;
import com.pro.dao.UserDaoImpl;

public class UserServiceImpl implements UserService {

    private UserDao userDao;
    public void setUserDao(UserDaoImpl userDao) {
        this.userDao = userDao;
    }

    public void save(String name) {
        userDao.insert(name);
        System.out.println("-----"+name+",ServiceImpl-------");
    }


}

三.配置好applicationContext.xml文件

  • 在XML引入AOP的约束,这个是实现aop必须要导入的约束,结合自己的xml文件,对比观察发现,每一个约束,无论是MVC的约束还是aop的,都是xmlns里面有一条链接xsi里面有成对的两条链接,所以要导入约束,注意是三条。
  • <?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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
     
     
    </beans>

    下面这个是自己写的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:p="http://www.springframework.org/schema/p"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <aop:aspectj-autoproxy/> <!--自动代理-->
    <bean id="asp" class="com.pro.util.MyAspect"/>
    <bean id="userDao" class="com.pro.dao.UserDaoImpl"/>
    <bean id="userService" class="com.pro.service.UserServiceImpl">
        <!--        这里为什么要写property 为了在UserServiceImpl里面不用new UserDao-->
        <property name = "userDao" ref = "userDao"/>
    </bean>
 <!--   <aop:aspectj-autoproxy/>&lt;!&ndash;自动代理&ndash;&gt;
    <bean id="asp" class="com.pro.util.MyAspect"/>
    <bean id="userDao" class="com.pro.dao.UserDaoImpl"/>
    <bean id="userService" class="com.pro.service.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>-->
</beans>

execution函数介绍


在通知中通过value属性定义切点,通过execution函数,可以定义切点的方法切入
1、切入点:实际增强的方法
2、常用的表达式
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
(1)execution(* com.tulun.bean.Book.show(..)) 表类里面的某一个方法
(2)execution(* com.tulun.bean.Book.*(..)) 表类某个包里类所有方法
(3)execution(* *.*(..)) 表示所有

例:
-匹配所有类public方法 execution(public *.*(..))
-匹配指定包下所有类方法 execution(* com.tulun.bean.*(..)) (不包含子包)
- execution(* com.tulun.bean..*(..)) (包含包、子包下所有类)
-匹配指定类所有方法 execution(* com.tulun.bean.Book.*(..))
-匹配实现特定接口所有类方法 execution(* com.tulun.bean.Book+.*(..))
-匹配所有com开头的方法 execution(* com*(..))

 

四.写一个MyAspect工具类,用来模拟新添加的功能

package com.pro.util;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class MyAspect {

    //第一个*号后面要有一个空格
    @Pointcut("execution(* com.pro.service..*.*(..))")//execution(* com.pro.service..*.*(..))实际上是一个方法
    public void all(){

    }
    @Before("all()")//表示在pointCut这个切面下的方法执行前,都会先执行这个say方法
    public void say(){
        System.out.println("林强 ,你好!");
    }
}

五.新建一个UserTest测试类

package com.pro.test;

import com.pro.service.UserService;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {
    public static void main(String[] args) {
        BeanFactory beanFactory  = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) beanFactory.getBean("userService");
        userService.save("小星星");
    }
}

六.执行效果:

  • 方式二:xml文件里面配置来实现

  • 区别就在于applicationContext.xml里面不一样自动代理不写,原本注解的方式改用配置xml文件,还有在添加的时候方法不要写注解,
  •  <!--
            aop:aspect标签
            配置切面
            把增强应用到切入点的过程
            ref属性:指定增强
             id属性:取名称
             order属性:给多个增强排序
            -->
    
      <!--
            aop:pointcut标签
            配置切入点
            对于要进行增强的连接点称之为切入点
            id属性:取名称
            expression:切入点表达式
            execution表达式
            -->
    

  • <!--    <aop:aspectj-autoproxy/> &lt;!&ndash;自动代理&ndash;&gt;-->
        <aop:config>
            <aop:pointcut id="all" expression="execution(* com.pro.service..*.*(..))"/>
            <aop:aspect ref="asp">
                <aop:after method="say" pointcut-ref="all"/>
                <aop:before method="say" pointcut-ref="all"/>
            </aop:aspect>
        </aop:config>
        <bean id="asp" class="com.pro.util.MyAspect"/>
        <bean id="userDao" class="com.pro.dao.UserDaoImpl"/>
        <bean id="userService" class="com.pro.service.UserServiceImpl">
            <!--        这里为什么要写property 为了在UserServiceImpl里面不用new UserDao-->
            <property name = "userDao" ref = "userDao"/>
        </bean>
     <!--   <aop:aspectj-autoproxy/>&lt;!&ndash;自动代理&ndash;&gt;
        <bean id="asp" class="com.pro.util.MyAspect"/>
        <bean id="userDao" class="com.pro.dao.UserDaoImpl"/>
        <bean id="userService" class="com.pro.service.UserServiceImpl">
            <property name="userDao" ref="userDao"/>
        </bean>-->
    </beans>

     七.总结:

    通过这两种种方式实现面向切面编程,就可以将模拟的MyAspect里面的新功能say方法,在不修改源代码的前提下,调用某个类(service)里面的方法时,在这个方法执行前或执行后增加进来。


网站公告

今日签到

点亮在社区的每一天
去签到