• Spring AOP配置


    一、XML配置方式

    1.创建一个Service类

    package com.spring.useage.service;
    
    public class UserService {
    
        public void save() {
            System.out.println("save a user.");
        }
        
        public void findById(String id) {
            System.out.println("find a user by id");
        }
        
        public void deleteUser() {
            System.out.println("a user is deleted.");
        }
    }

    2.创建一个切面类

    package com.spring.aop;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.aspectj.lang.JoinPoint;
    
    public class SecurityCheck {
        public final static Log log = LogFactory.getLog(SecurityCheck.class);
        
        public void check() {
            log.info("权限校验。。。");
        }
        
        public void addLog(JoinPoint joinPoint) {
            log.info("添加日志。。。");
            String methodName = joinPoint.getSignature().getName();
            log.info("方法名:" + methodName);
            log.info("方法参数:");
            Object[] args = joinPoint.getArgs();
            for (Object obj : args) {
                log.info(obj);
            }
        }
    }

    3.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-2.5.xsd
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    
        <bean id="securityCheck" class="com.spring.aop.SecurityCheck"></bean>
        <bean id="userService" class="com.spring.useage.service.UserService"></bean>
        <aop:config>
            <aop:aspect id="myAop" ref="securityCheck">
                <aop:pointcut id="target"
                    expression="execution(* com.spring.useage.service.*.*(..))" />
                <aop:before method="check" pointcut-ref="target" />
                <aop:after method="addLog" pointcut-ref="target" />
            </aop:aspect>
        </aop:config>
    </beans>

    execution(* com.spring.useage.service.*.*(..))说明:

    第1个*:表示所有返回值类型

    第2个*:表示com.spring.useage.service下的所有类

    第3个*:表示所有方法

    最后的..:表示任意参数

    需要引入的包如下:

    image

    4.测试类如下:

    package com.spring.aop;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.spring.useage.service.UserService;
    
    public class AopTest {
    
        /**
         *
         * @author qincd
         * @date Nov 24, 2014 6:30:00 PM
         */
        public static void main(String[] args) {
            ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
            UserService us = ac.getBean(UserService.class);
            us.save();
            us.findById("admin");
            us.deleteUser();
        }
    
    }

    执行AopTest,输出如下:

    2014-11-25 9:59:10 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@14d3343: startup date [Tue Nov 25 09:59:10 CST 2014]; root of context hierarchy
    2014-11-25 9:59:10 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [applicationContext.xml]
    2014-11-25 9:59:10 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
    信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1b3f829: defining beans [securityCheck,userService,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.aop.aspectj.AspectJPointcutAdvisor#0,org.springframework.aop.aspectj.AspectJPointcutAdvisor#1,target]; root of factory hierarchy
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck check
    信息: 权限校验。。。
    save a user.
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck addLog
    信息: 添加日志。。。
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck addLog
    信息: 方法名:save
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck addLog
    信息: 方法参数:
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck check
    信息: 权限校验。。。
    find a user by id
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck addLog
    信息: 添加日志。。。
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck addLog
    信息: 方法名:findById
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck addLog
    信息: 方法参数:
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck addLog
    信息: admin
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck check
    信息: 权限校验。。。
    a user is deleted.
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck addLog
    信息: 添加日志。。。
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck addLog
    信息: 方法名:deleteUser
    2014-11-25 9:59:10 com.spring.aop.SecurityCheck addLog
    信息: 方法参数:

    二、Annotation方式

    1.UserService类加上@Service注解

    package com.spring.useage.service;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService {
    
        public void save() {
            System.out.println("save a user.");
        }
        
        public void findById(String id) {
            System.out.println("find a user by id");
        }
        
        public void deleteUser() {
            System.out.println("a user is deleted.");
        }
    }

    2.SecurityCheck加上@Aspect和@Component注解

    package com.spring.aop;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class SecurityCheck {
        public final static Log log = LogFactory.getLog(SecurityCheck.class);
        
        @Before("execution (* com.spring.**.service.*.*(..))")
        public void check() {
            log.info("权限校验。。。");
        }
        
        @After("execution (* com.spring.**.service.*.*(..))")
        public void addLog(JoinPoint joinPoint) {
            log.info("添加日志。。。");
            String methodName = joinPoint.getSignature().getName();
            log.info("方法名:" + methodName);
            log.info("方法参数:");
            Object[] args = joinPoint.getArgs();
            for (Object obj : args) {
                log.info(obj);
            }
        }
    }

    1、@Aspect:意思是这个类为切面类

    2、@Componet:因为作为切面类需要Spring管理起来,所以在初始化时就需要将这个类初始化加入Spring的管理;

    3、@Befoe:切入点的逻辑(Advice)

    4、execution…:切入点语法

    applicationContext.xml加入aspectj自动代理,并启用注解。

    <?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"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    
        <aop:aspectj-autoproxy />
        <context:annotation-config />
        <context:component-scan base-package="com.spring" />
    </beans>

    当多个Advice个有相同的织入点。那么我们可以定义一个织入点集合,在需要使用的地方,调用就可以了。

    如:

    package com.spring.aop;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class SecurityCheck {
        public final static Log log = LogFactory.getLog(SecurityCheck.class);
        
        @Before("myPointCut()")
        public void check() {
            log.info("权限校验。。。");
        }
        
        @After("myPointCut()")
        public void addLog(JoinPoint joinPoint) {
            log.info("添加日志。。。");
            String methodName = joinPoint.getSignature().getName();
            log.info("方法名:" + methodName);
            log.info("方法参数:");
            Object[] args = joinPoint.getArgs();
            for (Object obj : args) {
                log.info(obj);
            }
        }
        
        @AfterReturning("myPointCut()")
        public void afterReturning() {
            log.info("method after returning...");
        }
        
        @Around("myPointCut()")
        public void around(ProceedingJoinPoint pjp) throws Throwable {
            log.info("method around start...");
            pjp.proceed();
            log.info("method around end...");
        }
        
        @AfterThrowing("myPointCut()")
        public void afterThrowing(JoinPoint joinPoint) {
            log.error(joinPoint.getSignature().getName() + "执行异常:" );
        }
        
        @Pointcut("execution (* com.spring..service.*.*(..))")
        public void myPointCut() {}
    }

    注意:那个空方法,只是为了给Pointcut起个名字,以方便别处使用

    AOP实现动态代理注意

    因为Spring要实现AOP(面向切面编程),需要加入切面逻辑的类就会生成动态代理。在动态代理类中加入切面类从而实现面向切面编程,但生成动态代理存在以下注意事项:

    1、 被动态代理的类如果实现了某一个接口,那么Spring就会利用JDK类库生成动态代理。

    2、 如果被动态代理的类没有实现某一个接口,那么Spring就会利用CGLIB类库直接修改二进制码来生成动态代理(因为利用JDK生成动态代理的类必须实现一个接口),需要在项目中引用CGLIB类库

    参考:http://blog.csdn.net/yuqinying112/article/details/7335416

  • 相关阅读:
    记录一下最近面试的总结
    网络模块相关面试题
    JVM 之类加载器
    一段简单的关于字符串的 Java 代码竟考察了这么多东西
    LeetCode 链表题 ( Java )
    MD5 加盐加密
    SpringMVC 学习笔记
    [redis]dict和rehash
    [redis]SDS和链表
    [go]包和工程管理
  • 原文地址:https://www.cnblogs.com/luckystar2010/p/4120410.html
Copyright © 2020-2023  润新知