• spring AOP


    本节要点:

    • 掌握AOP概念
    • 掌握AOP的有关术语
    • 掌握spring AOP框架的实现方式

    在文章“spring静态代理和动态代理”中演示了如何使用jdk动态代理功能实现一个最简单的AOP。使用代理对象将日志记录与业务逻辑无关的动作或任务提取出来,设计为一个服务类,这样的类可以称之为aspect(切面).

    1  AOP定义

    • u  AOP把软件系统分成两部分:核心关注点和横切关注点。所谓核心关注点,是业务处理的主要流程,也就是说这个解决方案要做的事。所谓横切关注点,是与核心关注点无关的部分,常常发生在核心关注点的多处,而各处基本相似,如日志 、权限等。
    • u  将Cross-cutting concern设计为通用,不介入特定业务对象的一个职责清楚的Aspect对象,这就是Aspect-oriented programming,缩写即AOP.

    AOP并不会取代OOP,而是作为OOP的补充。

    • u  AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。

    2  AOP有关术语

    • u  Advice (通知).

    Aspect的具体实现称之为Advice(处理).上例中DynaProxyHandler类中invoke方法就是Advice的一个具体实现.

    • u  Joinpoint(连接点)

    Advice在应用程序中被执行的时机称为Joinpoint(连接点),这个时机可能是某个方法被执行之前或之后(或两者都有).

    • u  Pointcut(切入点)

    一组连接点的集合,用于指定哪些Aspect在哪些Joinpoint中织入到应用程序之上.

    • u  Target(目标对象)

    一个Advice被应用的目标对象.(被AOP框架进行增强处理的对象)

    • u  Weave(织入)

    Advice被应用至目标对象之上的过程称这为织入(Weave)

    • u  AOP代理(AOP Proxy):

    由AOP框架创建的目标对象的代理对象。是被插入了advice的Target Object 。

    • u  引入:

    将方法者字段添加到被处理的类中。

    术语图解

      

    3  spring AOP框架的实现方式

    Spring中的AOP代理由Spring的Ioc容器负责生成、管理,其依赖关系也由Ioc容器负责管理。

    AOP编程只需要程序员参加3个部分:

    • u  定义普通业务组件
    • u  定义切入点
    • u  定义增强处理 (定义切面)

        进行AOP的关键就是定义切入点和增强处理。一旦定义了合适的切入点和增强处理,AOP框架将会自动生成AOP代理。

    通常采用AspectJ方式来定义切入点和增强处理,在这种方式下,Spring有如下两种选择来定义切入点和增强处理:

    • 基于注解(Annotation)方式:使用@aspect、@Pointcut等Annotation来标注切入点和增强处理。
    • 基于XML配置文件的管理方式:使用spring配置文件来定义切入点和增强处理

    3.1 通过xml配置的方式实现

    加入jar包: aopalliance-1.0.jar,aspectjweaver.jar

    Log.java前置通知

    public class Log implements MethodBeforeAdvice{
    
        /**
    
         * @param method 被调用的方法对象,如addUser()方法
    
         * @param args 被调用的方法的参数
    
         * @param target 被调用的方法的目标对象
    
         */
    
        @Override
    
        public void before(Method method, Object[] args, Object target)
    
                throws Throwable {
    
            System.out.println("执行"+target.getClass().getName()+"的   "+method.getName()+"方法");
    
        }
    
    }

    afterLog.java后置通知

    public class AfterLog implements AfterReturningAdvice{
    
        /**
    
         * 目标方法执行后执行的通知
    
         * returnValue 返回值
    
         * method 被调用的方法对象
    
         * args 被调用方法对象的参数
    
         * target 被调用方法对象的目标对象
    
         */
    
        @Override
    
        public void afterReturning(Object returnValue, Method method, Object[] args,
    
                Object target) throws Throwable {
    
            System.out.println("after "+target.getClass().getName()+" 的 "+method.getName()+" 被执行");
    
        }
    
    }

     UserService

    public interface UserService {
    
        public void getUser();
    
        public void addUser();
    
        public void delUser(String ss);
    
        public void updUser();
    
    }

    UserServiceImpl

    public class UserServiceImpl implements UserService{
    
        @Override
    
        public void getUser() {
    
            System.out.println("get user");
    
        }
    
        @Override
    
        public void addUser() {
    
            System.out.println("add user");
    
        }
    
        @Override
    
        public void delUser( String ss) {
    
            System.out.println("delete user="+ss);
    
        }
    
        @Override
    
        public void updUser() {
    
            System.out.println("update user");
    
        }
    
    }

     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: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/aop
    
            http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <bean name="userService" class="com.silvan.service.UserServiceImpl"></bean>
    
        <!-- 定义切面 -->
    
        <bean name="log" class="com.silvan.log.Log"></bean>
    
        <bean name="afterLog" class="com.silvan.log.AfterLog"/>
    
        <aop:config>
    
        <!-- aop:pointcut指定哪些对象的哪些方法订阅切面, expression指定该切入点关联的切入点表达式  id指定该切入点的标识符-->
    
        <aop:pointcut expression="execution(* com.silvan.service.*.*(..))" id="pointcut"/>
    
        <!--aop:advisor指定切面关联哪个切入点   advice-ref指定切面  pointcut-ref指定切入点 -->
    
        <aop:advisor advice-ref="log" pointcut-ref="pointcut" />
    
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    
        </aop:config>
    
    </beans>

    Test

    public class Test {
    
        public static void main(String[] args) {
    
            ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
    
            UserService us = (UserService) ac.getBean("userService");
    
    //      us.delUser("zhaoliyin");
    
            us.updUser();
    
        }
    
    }

    使用log4j输出日志:

    加入jar包:log4j-1.2.14.jar

    配置文件:log4j.properties

    public class Log implements MethodBeforeAdvice{
    
        private Logger logger = Logger.getLogger(Log.class) ;
    
        @Override
    
        public void before(Method method, Object[] args, Object target)
    
                throws Throwable {
    
            logger.info("执行"+target.getClass().getName()+"的   "+method.getName()+"方法");
    
        }
    
    }

    3.2 通过注释的方式实现

    修改配置文件

    <?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.xsd
    
            http://www.springframework.org/schema/aop
    
            http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <aop:aspectj-autoproxy/>
    
        <bean name="userService" class="com.silvan.service.UserServiceImpl"></bean>
    
        <bean name="log" class="com.silvan.log.Log"></bean>
    
    </beans>

    修改切面内容

    import org.aspectj.lang.annotation.AfterReturning;
    
    import org.aspectj.lang.annotation.Aspect;
    
    import org.aspectj.lang.annotation.Before;
    
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    
    public class Log{
    
        @Pointcut("execution(* com.silvan.service.*.*(..))") 
    
        private void anyMethod(){}//定义一个切入点 
    
       
    
        @Before("anyMethod() && args(name)")
    
        public void before(String name){
    
            System.out.println("前置通知 "+name);
    
        }
    
        @AfterReturning("anyMethod()") 
    
        public void doAfter(){ 
    
            System.out.println("后置通知"); 
    
        } 
    
    }
  • 相关阅读:
    openwrt 的依赖找不到问题
    数据包与IPTABLE关系
    wifidog 配置中文说明
    Java 线程
    Java 集合
    IDEA配置Maven并创建web项目
    逻辑覆盖
    获得天气数据
    小程序项目文件介绍
    window 10 使用git
  • 原文地址:https://www.cnblogs.com/zhouyeqin/p/7208628.html
Copyright © 2020-2023  润新知