• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • Spring框架簡介⑧

    標簽: spring  java

    AOP, 面向切面編程

     Aspect, 對橫切性關注點的一種抽象(簡而言之, 上面講到的動態代理就是一種橫切面)

    相對而言, 類是對物體的一種抽象, 而切面是對橫切性關注點的一種抽象

    JoinPoint(連接點): 要攔截的方法

    PointCut(切點): 連接點的集合

    Advice(通知): 在連接點前后或異常情況發生時做的事情, 如前置通知/后置通知/返回通知/異常通知/環繞通知

     

    引包: 鏈接:https://pan.baidu.com/s/1lyoSeLmkkFJurBF_4GFH4g 密碼:hyz8

     

    1 注解方式配置切面

        ①前置通知(@Before)

    <?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: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-3.2.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-3.2.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    
        <!-- 開啟切面驅動(注解方式) -->
    	<aop:aspectj-autoproxy/>
    	
    	<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
    </beans>

    配置切面類PermAspect(添加注解@Aspect):

    package com.rl.spring.aspect;
    
    import org.aspectj.lang.annotation.Aspect;
    
    @Aspect
    public class PermAspect {
    
        
    }
    

    配置PermAspect類里面的切點和通知

    package com.rl.spring.aspect;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class PermAspect {
    
        /**
         * 第一個*: 代表任意返回值, 如果具體返回值 如: java.lang.String
         * 第二個*: 代表任意類
         * 第三個*: 代表任意方法
         * 第一個..: 代表service包下所有類和子包下的所有類
         * 第二個..: 代表方法的參數
         * 
         * 配置完成后 該方法即可攔截service及其子包下的任何類 任何返回值 任何方法以及任何參數
         */
        @Pointcut("execution(* com.rl.spring.service..*.*(..))")
        public void anyMethod() {
            
        }
        
        /**
         * 前置通知
         */
        @Before("anyMethod()")
        public void preAdive() {
            System.out.println("前置通知執行了...");
        }
    }
    

    需要先配置PermAspect類的bean

    <?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: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-3.2.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-3.2.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    
        <!-- 開啟切面驅動(注解方式) -->
    	<aop:aspectj-autoproxy/>
    	
    	<!-- 配置切面bean -->
    	<bean id="permAspect" class="com.rl.spring.aspect.PermAspect"></bean>
    	
    	<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
    </beans>

    測試一下:

    測試代碼:

    package com.rl.spring.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.rl.spring.service.UserService;
    
    @RunWith(value=SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
    public class TestSpring {
    	
        @Autowired
        UserService userService;
        
        @Test
        public void test() {
            userService.save();
        }
    }

    測試結果:

     

    傳參的方式:

    UserServiceImpl:

    package com.rl.spring.service.impl;
    
    import com.rl.spring.model.User;
    import com.rl.spring.service.UserService;
    public class UserServiceImpl implements UserService {
    
        private User user;
        
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    
        @Override
        public void save(User user) {
            System.out.println("保存用戶..."+user);
        }
    
        @Override
        public void update() {
            System.out.println("修改用戶...");
        }
    }
    

    PermAspect:

    package com.rl.spring.aspect;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    
    import com.rl.spring.model.User;
    
    @Aspect
    public class PermAspect {
    
        /**
         * 配置切面方法
         * 
         * 第一個*: 代表任意返回值, 如果具體返回值 如: java.lang.String
         * 第二個*: 代表任意類
         * 第三個*: 代表任意方法
         * 第一個..: 代表service包下所有類和子包下的所有類
         * 第二個..: 代表方法的參數
         * 
         * 配置完成后 該方法即可攔截service及其子包下的任何類 任何返回值 任何方法以及任何參數
         */
        @Pointcut("execution(* com.rl.spring.service..*.*(..))")
        public void anyMethod() {
            
        }
        
        /**
         * 前置通知
         * anyMethod(): 指定切面方法
         * args(*): 指定傳參, * 為參數名, 在這里args的參數名稱必須和方法參數的名稱相同 在此例中必須為user
         *          如果有多個參數, 則直接用逗號隔開即可 
         */
        @Before("anyMethod()&&args(user)")
        public void preAdive(User user) {
            System.out.println(user);
            //可以做一些操作
            user.setUsername("火星");
            System.out.println("前置通知執行了...");
        }
    }
    

    測試代碼:

    package com.rl.spring.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.rl.spring.model.User;
    import com.rl.spring.service.UserService;
    
    @RunWith(value=SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
    public class TestSpring {
    	
        @Autowired
        UserService userService;
        
        @Test
        public void test() {
            User user = new User();
            user.setUserId(1);
            user.setUsername("lijialin");
            user.setPassword("123");
            userService.save(user);
        }
    }

    測試結果:

        ②后置通知(@After)

    將配置文件中的bean改為新建的PermAspect1

    <?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: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-3.2.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-3.2.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    
        <!-- 開啟切面驅動(注解方式) -->
    	<aop:aspectj-autoproxy/>
    	
    	<!-- 配置切面bean -->
    	<bean id="permAspect" class="com.rl.spring.aspect.PermAspect1"></bean>
    	
    	<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
    </beans>

    PermAspect1

    package com.rl.spring.aspect;
    
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    
    import com.rl.spring.model.User;
    
    @Aspect
    public class PermAspect1 {
    
        @Pointcut("execution(* com.rl.spring.service..*.*(..))")
        public void anyMethod() {
            
        }
        
        @After(value="anyMethod()")
        public void postAdvice() {
            System.out.println("執行后置通知...");
        }
    }
    

    測試代碼:

    package com.rl.spring.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.rl.spring.model.User;
    import com.rl.spring.service.UserService;
    
    @RunWith(value=SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
    public class TestSpring {
    	
        @Autowired
        UserService userService;
        
        @Test
        public void test() {
            User user = new User();
            user.setUserId(1);
            user.setUsername("lijialin");
            user.setPassword("123");
            userService.save(user);
        }
        
        @Test
        public void test1() {
            userService.save();
        }
    }

     

        ③返回通知(@AfterReturning)

    返回通知代碼:

    package com.rl.spring.aspect;
    
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    
    import com.rl.spring.model.User;
    
    @Aspect
    public class PermAspect1 {
    
        @Pointcut("execution(* com.rl.spring.service..*.*(..))")
        public void anyMethod() {
            
        }
        
        
        
        /**
         * @AfterReturning: 返回通知的注解, 在返回通知里面可以對業務方法的返回值做最后的統一加工處理
         * pointcut: 指定返回通知的切點
         * returning: 指定返回值和返回通知的方法的參數名稱要一致
         */
        @AfterReturning(pointcut="anyMethod()", returning="user")
        public void returnAdvice(User user) {
            user.setUsername("lijialin");//統一加工處理
            System.out.println("執行返回通知...");
        }
    }
    

    測試代碼:

    package com.rl.spring.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.rl.spring.model.User;
    import com.rl.spring.service.UserService;
    
    @RunWith(value=SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
    public class TestSpring {
    	
        @Autowired
        UserService userService;
        
        
        
        @Test
        public void test2() {
            User user = userService.queryById(1);
            System.out.println("最終返回的user: "+user);
        }
    }

    輸出結果:

        ④例外通知(異常通知) @ AfterThrowing 主要用于運行期的監控, 異常時拋出處理

    在UserServiceImpl方法中設置一個異常1/0

    異常通知代碼:

    package com.rl.spring.aspect;
    
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    
    import com.rl.spring.model.User;
    
    @Aspect
    public class PermAspect1 {
    
        @Pointcut("execution(* com.rl.spring.service..*.*(..))")
        public void anyMethod() {
            
        }
        
        
        
        @AfterThrowing(pointcut="anyMethod()", throwing="ex")
        public void exceptionAdvice(Exception ex) {
            System.out.println("執行例外通知...");
            ex.printStackTrace();
        }
    }
    

    測試代碼:

    package com.rl.spring.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.rl.spring.model.User;
    import com.rl.spring.service.UserService;
    
    @RunWith(value=SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
    public class TestSpring {
    	
        @Autowired
        UserService userService;
       
        
        @Test
        public void test1() {
            userService.save();
        }
        
    }

    結果輸出:

     

        ⑤環繞通知(@Around 用的最多, 可以實現前置通知 后置通知 返回通知 例外通知的所有功能)

    環繞通知代碼:

    package com.rl.spring.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    
    import com.rl.spring.model.User;
    
    @Aspect
    public class PermAspect2 {
    
        @Pointcut("execution(* com.rl.spring.service..*.*(..))")
        public void anyMethod() {
            
        }
        
        /**
         * @Around: 環繞通知的注解, 指定切點
         * ProceedingJoinPoint: 正在執行的連接點, 正在執行攔截的方法的抽象
         * @throws Throwable 
         */
        @Around("anyMethod()")
        public Object doAroundAdvice(ProceedingJoinPoint jp) throws Throwable {
            Object[] args = jp.getArgs();//獲得參數
            System.out.println("環繞通知前--前置通知..."+args[0]);//本次示例參數只有一個, 取索引0
            
            //環繞通知的執行方法, 如果使用無參 則傳遞默認參數 返回值就是業務方法的返回值
    //        Object obj = jp.proceed();//讓方法繼續走下去
            Object obj = jp.proceed(args);//此參數可以修改后再傳遞過去, 這樣就跟原先的參數值不一樣的了 但本例中沒改, 直接傳回去
            User user = (User) obj;
            user.setUsername("lijialin");
            System.out.println("環繞通知后--后置通知..."+"  返回值: "+obj);
            return obj;
        }
    }

    測試代碼:

    package com.rl.spring.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.rl.spring.model.User;
    import com.rl.spring.service.UserService;
    
    @RunWith(value=SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
    public class TestSpring {
    	
        @Autowired
        UserService userService;
        
       
        
        @Test
        public void test3() {
            User user = userService.queryById(1);
            System.out.println(user);//也能將返回值輸出
        }
    }

    利用環繞通知配置權限

    環繞通知代碼:

    package com.rl.spring.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    
    import com.rl.spring.model.User;
    import com.rl.spring.service.impl.UserServiceImpl;
    
    @Aspect
    public class PermAspect2 {
        
        @Pointcut("execution(* com.rl.spring.service..*.*(..))")
        public void anyMethod() {
            
        }
        
        
        @Around("anyMethod()")
        public Object doAroundAdvice(ProceedingJoinPoint jp) throws Throwable {
            
            UserServiceImpl us = (UserServiceImpl) jp.getTarget();
            User user = us.getUser();
            Object obj = null;
            if(user != null) {
                obj = jp.proceed();
            }else {
                System.out.println("您還沒有登錄呢!");
            }
            return obj;
        }
    }

    測試代碼:

    package com.rl.spring.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.rl.spring.model.User;
    import com.rl.spring.service.UserService;
    
    @RunWith(value=SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
    public class TestSpring {
    	
        @Autowired
        UserService userService;
       
        
        @Test
        public void test4() {
            userService.save(new User());//這里即使是new了一個User 在業務類里面的User還是為null
        }
    }

    輸出結果:

     

    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: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-3.2.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-3.2.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    
    	<!-- 配置切面bean -->
    	<bean id="permAspect" class="com.rl.spring.aspect.PermAspect"></bean>
    	
    	<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
    	
    	<!-- 配置aop -->
    	<aop:config>
    	<!-- 配置切點 -->
    	   <aop:pointcut expression="execution(* com.rl.spring.service..*.*(..))" id="mycut"/>
    	   <!-- 配置切面 -->
    	   <aop:aspect ref="permAspect">
    	   <!-- 指定切面中的方法為前置通知 -->
    	       <aop:before method="preAdvice" pointcut-ref="mycut"/>
    	   </aop:aspect>
    	</aop:config>
    </beans>

    切面代碼:

    package com.rl.spring.aspect;
    
    import org.aspectj.lang.JoinPoint;
    
    public class PermAspect {
    
        /**
         * 無需注解配置了, 已經在配置文件中定義好了
         */
        public void preAdvice(JoinPoint jp) {
            Object[] args = jp.getArgs();
            System.out.println("執行前置通知..."+"參數: "+args[0]);
        }
    }
    

    測試代碼:

    package com.rl.spring.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.rl.spring.model.User;
    import com.rl.spring.service.UserService;
    
    @RunWith(value=SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
    public class TestSpring {
    	
        @Autowired
        UserService userService;
        
        @Test
        public void test() {
            User user = new User();
            user.setUserId(1);
            user.setUsername("lijialin");
            user.setPassword("123");
            userService.save(user);
        }
        
    }

    輸出結果:

    后置通知:

    與前置通知同理:

    輸出結果:

    返回通知:

    返回通知代碼:

    package com.rl.spring.aspect;
    
    import org.aspectj.lang.JoinPoint;
    
    import com.rl.spring.model.User;
    
    public class PermAspect {
    
       
        
        public void returnAdvice(JoinPoint jp, Object returnval) {
            if(returnval instanceof User) {
                User user = (User) returnval;
                user.setUsername("lijialin");
            }
            System.out.println("返回通知..."+"返回的值: "+returnval);
        }
    }
    

    配置文件:

    <?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: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-3.2.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-3.2.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    
    	<!-- 配置切面bean -->
    	<bean id="permAspect" class="com.rl.spring.aspect.PermAspect"></bean>
    	
    	<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
    	
    	<!-- 配置aop -->
    	<aop:config>
    	<!-- 配置切點 -->
    	   <aop:pointcut expression="execution(* com.rl.spring.service..*.*(..))" id="mycut"/>
    	   <!-- 配置切面 -->
    	   <aop:aspect ref="permAspect">
    	   <!-- 指定切面中的方法為前置通知 -->
    	       <aop:before method="preAdvice" pointcut-ref="mycut"/>
    	       <aop:after method="afterAdvice" pointcut-ref="mycut"/>
    	       <aop:after-returning method="returnAdvice" pointcut-ref="mycut" returning="returnval"/>
    	   </aop:aspect>
    	</aop:config>
    </beans>

    測試代碼:

    package com.rl.spring.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.rl.spring.model.User;
    import com.rl.spring.service.UserService;
    
    @RunWith(value=SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations= {"classpath:ApplicationContext.xml"})
    public class TestSpring {
    	
        @Autowired
        UserService userService;
        
        @Test
        public void test1() {
            User user = userService.queryById(1);
            System.out.println(user);
        }
    }

    輸出結果:

    例外通知:

    例外通知代碼:

    package com.rl.spring.aspect;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    
    import com.rl.spring.model.User;
    
    public class PermAspect {
    
        /**
         * 無需注解配置了, 已經在配置文件中定義好了
         */
        public void preAdvice(JoinPoint jp) {
            Object[] args = jp.getArgs();
            if(args.length>0)
            System.out.println("執行前置通知..."+"參數: "+args[0]);
        }
        
        public void afterAdvice(JoinPoint jp) {
            Object[] args = jp.getArgs();
            if(args.length>0)
            System.out.println("執行后置通知..."+"參數: "+args[0]);
        }
        
        public void returnAdvice(JoinPoint jp, Object returnval) {
            if(returnval instanceof User) {
                User user = (User) returnval;
                user.setUsername("lijialin");
            }
            System.out.println("返回通知..."+"返回的值: "+returnval);
        }
        
        public void exceptionAdvice(JoinPoint jp, Exception ex) {
            System.out.println("例外通知...");
            ex.printStackTrace();
        }
        
       
    }
    

    配置文件:

    <?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: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-3.2.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-3.2.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    
    	<!-- 配置切面bean -->
    	<bean id="permAspect" class="com.rl.spring.aspect.PermAspect"></bean>
    	
    	<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
    	
    	<!-- 配置aop -->
    	<aop:config>
    	<!-- 配置切點 -->
    	   <aop:pointcut expression="execution(* com.rl.spring.service..*.*(..))" id="mycut"/>
    	   <!-- 配置切面 -->
    	   <aop:aspect ref="permAspect">
    	   <!-- 指定切面中的方法為前置通知 -->
    	       <aop:before method="preAdvice" pointcut-ref="mycut"/>
    	       <aop:after method="afterAdvice" pointcut-ref="mycut"/>
    	       <aop:after-returning method="returnAdvice" pointcut-ref="mycut" returning="returnval"/>
    	       <!-- 
    	           throwing: 拋出的異常變量名, 需要跟切面類里面的變量匹配
    	        -->
    	       <aop:after-throwing method="exceptionAdvice" pointcut-ref="mycut" throwing="ex"/>
    	      
    	   </aop:aspect>
    	</aop:config>
    </beans>

     

    結果輸出:

     

    環繞通知:

    環繞通知代碼:

    package com.rl.spring.aspect;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    
    import com.rl.spring.model.User;
    
    public class PermAspect {
    
        /**
         * 無需注解配置了, 已經在配置文件中定義好了
         */
        public void preAdvice(JoinPoint jp) {
            Object[] args = jp.getArgs();
            if(args.length>0)
            System.out.println("執行前置通知..."+"參數: "+args[0]);
        }
        
        public void afterAdvice(JoinPoint jp) {
            Object[] args = jp.getArgs();
            if(args.length>0)
            System.out.println("執行后置通知..."+"參數: "+args[0]);
        }
        
        public void returnAdvice(JoinPoint jp, Object returnval) {
            if(returnval instanceof User) {
                User user = (User) returnval;
                user.setUsername("lijialin");
            }
            System.out.println("返回通知..."+"返回的值: "+returnval);
        }
        
        public void exceptionAdvice(JoinPoint jp, Exception ex) {
            System.out.println("例外通知...");
            ex.printStackTrace();
        }
        
        public Object aroundAdvice(ProceedingJoinPoint jp) {
            Object[] objs = jp.getArgs();
            Object obj = null;
            System.out.println("環繞通知之前置通知...");
            if(objs.length>0) {
                System.out.println("執行環繞通知..."+"參數: "+objs[0]);
                try {
                    obj = jp.proceed();
                    System.out.println("環繞通知之后置通知...");
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
            return obj;
        }
    }
    

    配置文件:

    <?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: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-3.2.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-3.2.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    
    	<!-- 配置切面bean -->
    	<bean id="permAspect" class="com.rl.spring.aspect.PermAspect"></bean>
    	
    	<bean id="userService" class="com.rl.spring.service.impl.UserServiceImpl"></bean>
    	
    	<!-- 配置aop -->
    	<aop:config>
    	<!-- 配置切點 -->
    	   <aop:pointcut expression="execution(* com.rl.spring.service..*.*(..))" id="mycut"/>
    	   <!-- 配置切面 -->
    	   <aop:aspect ref="permAspect">
    	   <!-- 指定切面中的方法為前置通知 -->
    	       <aop:before method="preAdvice" pointcut-ref="mycut"/>
    	       <aop:after method="afterAdvice" pointcut-ref="mycut"/>
    	       <aop:after-returning method="returnAdvice" pointcut-ref="mycut" returning="returnval"/>
    	       <!-- 
    	           throwing: 拋出的異常變量名, 需要跟切面類里面的變量匹配
    	        -->
    	       <aop:after-throwing method="exceptionAdvice" pointcut-ref="mycut" throwing="ex"/>
    	       <aop:around method="aroundAdvice" pointcut-ref="mycut"/>
    	   </aop:aspect>
    	</aop:config>
    </beans>

    結果輸出:

    版權聲明:本文為ip_JL原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/ip_JL/article/details/81490540

    智能推薦

    Spring框架學習_Spring簡介(02)

    這里寫自定義目錄標題 簡單了解框架 第一章 Spring 概述 # 1.1 Spring概述 # 1.2 Spring模塊 簡單了解框架 第一章 Spring 概述 # 1.1 Spring概述 1)Spring是一個開源框架 2)Spring為簡化企業級開發而生,使用Spring,JavaBean就可以實現很多以前要靠EJB才能實現的功能。同樣的功能,在EJB中要通過繁瑣的配置和復雜的代碼才能夠...

    Spring框架簡介以及環境搭建

    1.spring概述 Spring是一個開源框架,Spring是于2003 年興起的一個輕量級的Java 開發框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中闡述的部分理念和原型衍生而來。它是為了解決企業應用開發的復雜性而創建的。框架的主要優勢之一就是其分層架構,分層架構允許使用者選擇使用哪一個組件,同時為 J2E...

    安全框架(一)Spring Security 簡介

    安全框架: Spring Security+Shiro+OAuth2在一個項目里面 github地址: https://github.com/ZiCheng-Web/springboot-security 在 Java 開發領域常見安全框架有 Shiro 和Spring Security。 Shiro 是個一個輕量級的安全管理框架,提供了認證、授權、 會話管理、密碼管理、緩存管理等功能,。 Spr...

    Spring框架學習01:簡介和IoC

    一、Spring框架簡介 1.Spring歷史 2002,首次推出了spring框架的雛形,interface21框架! spring框架即以interface21框架為基礎,經過重新設計,并不斷豐富其內涵,于2003年3月24日發布了1.0正式版。 Rod Johnson,spring framework創始人,著名作者。很難想象Rod Johnson的學歷,真的讓好多人大吃一驚,他是悉尼大學的...

    Spring 框架簡介及簡單環境搭建

    Spring 框架簡介 概述 Spring 是最受歡迎的企業級 Java 應用程序開發框架 Spring 框架是一個開源的 Java 平臺,它最初是由 Rod Johnson 編寫的 Spring 是輕量級的框架 宗旨 不產生新技術,使原有的技術使用更加方便 核心 Ioc/DI:控制反轉/依賴注入 AOP:面向切面編程 聲明式事務 Spring Framework Runtime Test:Spr...

    猜你喜歡

    portlet_Spring Portlet MVC框架簡介

    本文是由三部分組成的文章系列的第一篇文章,“開發供在IBM WebSphere Portal中使用的Spring Portlet MVC Framework應用程序”。 這是一篇高級文章; 盡管不需要任何高級知識,但您應該熟悉開發JSR-168 Portlet的基礎知識,并且對Spring框架有基本的了解。 在過去的幾年中, Spring框架在J2EE開發人員中越來越受歡迎...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    精品国产乱码久久久久久蜜桃不卡