zoukankan      html  css  js  c++  java
  • AOP面向切面编程的四种实现

              一.AOP(面向切面编程)的四种实现分别为最原始的经典AOP、代理工厂bean(ProxyFacteryBean)和默认自动代理DefaultAdvisorAutoProxyCreator以及BeanNameAutoProxyCreator代理、Aspectj的注解和xml配置文件。

         1.代理工厂bean(ProxyFacteryBean)的方式

          1.1 接口(Interface)

    1 package cn.happy.interfaces;
    2 
    3 public interface Advice {
    4 
    5     public void fristMethod();
    6     
    7     public String secondMethod();
    8 }

             1.2  接口的实现类

     1 package cn.happy.impl;
     2 
     3 import cn.happy.interfaces.Advice;
     4 
     5 public class AdviceImpl implements Advice {
     6 
     7     public void fristMethod() {
     8          System.out.println("==fristMethod==");
     9     }
    10 
    11     public String secondMethod() {
    12         System.out.println("==secondMethod==");
    13         return "abc";
    14     }
    15 
    16 }

             1.3 各种通知增强

           1.3.1 前置增强

     1 package cn.happy.advice;
     2 
     3 import java.lang.reflect.Method;
     4 
     5 public class MethodBeforeAdvice implements
     6         org.springframework.aop.MethodBeforeAdvice {
     7 
     8     public void before(Method arg0, Object[] arg1, Object arg2)
     9             throws Throwable {
    10         System.out.println("==Before==");
    11          
    12     }
    13 
    14 }

            1.3.2  后置增强

     1 package cn.happy.advice;
     2 
     3 import java.lang.reflect.Method;
     4 
     5 import org.springframework.aop.AfterReturningAdvice;
     6 
     7 public class AfterReturningAdvie implements AfterReturningAdvice {
     8 
     9     public void afterReturning(Object arg0, Method arg1, Object[] arg2,
    10             Object arg3) throws Throwable {
    11         System.out.println("==After==");
    12 
    13     }
    14 
    15 }

          1.3.3  环绕增强

    package cn.happy.aroundadvice;
    
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    
    public class MyInterceptor implements MethodInterceptor{
    
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("==before==");
            String result= (String)invocation.proceed();
            System.out.println("==after==");
            return result;
        }
    }

            

          1.3.4 异常增强

    package cn.happy.exception;
    
    import org.springframework.aop.ThrowsAdvice;
    
    public class MyException implements ThrowsAdvice {
        public void afterThrowing(Exception ex){
            System.out.println("异常通知");
        }
    }

            

             1.4 配置文件

    <?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" 
        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">
            
            <!-- 实现类的引入 -->
            <bean id="adviceimpl" class="cn.happy.impl.AdviceImpl"></bean>
           <!-- 前置增强  通知-->
            <bean id="advicebefore" class="cn.happy.advice.MethodBeforeAdvice"></bean>
            <!-- 后置增强  通知-->
            <bean id="adviceafter" class="cn.happy.advice.AfterReturningAdvie"></bean>
            
            <!-- 环绕增强 -->
            <bean id="around" class="cn.happy.aroundadvice.MyInterceptor"></bean>
            
            <!-- 关联  代理工厂bean ProxyFacteryBean 通知 -->
            <!--<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
               
               <property name="targetName" value="adviceimpl"></property>
               <property name="interceptorNames" value="advicebefore,adviceafter"></property>
               
            </bean>-->
            
            <!-- 环绕增强 代理工厂 顾问包装通知 -->
            <bean id="aroundserviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
               
               <property name="target" ref="adviceimpl"></property>
               <property name="interceptorNames" value="beforeadvisor"></property>
               
            </bean>
            
            <!-- 切面  通知  -->
            <bean id="beforeadvice" class="cn.happy.mymethodbefore.MyMethodBeforeAdvice"></bean>
            
            <!-- 顾问  包装advice -->
            <bean id="beforeadvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
             <property name="advice" ref="beforeadvice"></property>
             <property name="mappedNames" value="fristMethod,secondMethod"></property>
            </bean>
            
            <!-- 顾问  包装advice 正则表达式-->
            <!--<bean id="beforeadvisor1" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
             <property name="advice" ref="beforeadvice"></property>
             <property name="pattern" value=".*Method.*"></property>
            </bean>-->
            
            
            <!-- 默认自动代理  默认只找通知-->
            <!--<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>-->
            
            <!-- beanname自动代理 可以选择顾问或者通知-->
            <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
              <property name="beanNames" value="adviceimpl"></property>
              <property name="interceptorNames" value="beforeadvisor"></property>
            </bean>
            
    </beans>

      

           1.5 测试类

    package cn.happy.test;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import cn.happy.interfaces.Advice;
    
    public class Test {
        /**
         * 通知的前置和后置测试
         */
        public static void main(String[] args) {
            //解析配置文件
            ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
            Advice advice= (Advice)ctx.getBean("adviceimpl"); //自动代理beanname的方式
            advice.fristMethod();
            advice.secondMethod();
        }
    }

           2. 最原始的经典AOP

        2.1 最基本分层模式dao、biz、service以及最后测试Test

        2.1.1DAO层

    package cn.happy.dao;
    
    import cn.happy.entity.User;
    
       //接口
    public interface UDao {
    
        //保存方法
        public void save(User user);
    }
    
     //实现类
    package cn.happy.dao;
    
    import cn.happy.entity.User;
    
    public class UserDaoImpl implements UDao{
    
        public void save(User user) {
            System.out.println("保存成功");
        }
    
    }

         2.1.2 BIZ层

    package cn.happy.biz;
    
    import cn.happy.entity.User;
    
      //业务接口
    public interface UBiz {
    
        //保存方法
        public void save2(User user);
    }
    
      //业务实现类
    package cn.happy.biz;
    
    import cn.happy.dao.UDao;
    import cn.happy.entity.User;
    
    public class UserBiz implements UBiz{
    
        //dao的对象
        private UDao udao;
        public void save2(User user) {
            udao.save(user);
            
        }
        public UDao getUdao() {
            return udao;
        }
        public void setUdao(UDao udao) {
            this.udao = udao;
        }
       
    }

         2.1.3  AOP模块即service层

    package cn.happy.logger;
    
    import java.lang.reflect.Method;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
      //前置内容
    public class LoggerBefore implements MethodBeforeAdvice {
    
        public void before(Method arg0, Object[] arg1, Object arg2)
                throws Throwable {
            System.out.println("save前置内容");   
        }
    }
    
    
    //后置内容
    package cn.happy.logger;
    import java.lang.reflect.Method;
    import org.springframework.aop.AfterReturningAdvice;
    
    public class LoggerAfter implements AfterReturningAdvice{
    
        public void afterReturning(Object arg0, Method arg1, Object[] arg2,
                Object arg3) throws Throwable {
            System.out.println("save后置内容");   
        }
    }

          2.1.4 经典的配置文件

    <?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-4.1.xsd">
            <!-- 业务biz与dao接口对象的实现 -->
            <bean id="dao" class="cn.happy.dao.UserDaoImpl"></bean>
            <bean id="biz" class="cn.happy.biz.UserBiz">
                <property name="udao" ref="dao"></property>
            </bean> 
            <!-- 前置与后置内容的配置 -->
            <bean id="before" class="cn.happy.logger.LoggerBefore"></bean>
            <bean id="after" class="cn.happy.logger.LoggerAfter"></bean>
            <!-- aop的配置 -->
            <aop:config>
              <aop:pointcut expression="execution(public void save2(cn.happy.entity.User))" id="pointcut"/>
              <!-- 在切入点处插入增强处理、完成"织入" -->
              <aop:advisor advice-ref="before" pointcut-ref="pointcut"/>
              <aop:advisor advice-ref="after" pointcut-ref="pointcut"/>
            </aop:config>
    </beans>       

         2.1.5  测试类

    package cn.happy.test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import cn.happy.biz.UBiz;
    import cn.happy.entity.User;
    
    public class AOPTest {
    
        public static void main(String[] args) {
            ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
            UBiz ubiz=(UBiz)context.getBean("biz");
            User user=new User();
            ubiz.save2(user);
            System.out.println("save~ok");
        }
    }

           3. 然后就是Aspectj的注解以及xml配置文件的两种方式了。

         3.1 Aspectj注解

         3.1.1 接口和实现类

    package cn.happy.impl;
    //接口
    public interface AspectDao {
          
        public void add();
        public void delete();
    }
    
    //实现类
    package cn.happy.impl;
    
    public class AspectjIpml implements AspectDao{
        //添加
        public void add() {
            System.out.println("==ADD==");
        }
        //删除
        public void delete() {
            System.out.println("==DELETE==");   
        }
    }

          

          3.1.2 注解类Aspect

    package cn.happy.aspectj;
    
    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.Before;
    
    @org.aspectj.lang.annotation.Aspect
    public class Aspect {
        //前置增强
         @Before(value="execution(public * *(..))")
        public void asBefore(){
            System.out.println("这是前置增强");
        }
       //后置增强
         @AfterReturning(value="execution(public * *(..))")
        public void asAfterReturning(){
            System.out.println("这是后置增强");
        }
       //环绕增强
         @Around(value="execution(public * *(..))")
        public void asAround(ProceedingJoinPoint pj){
             System.out.println("这是环绕前置增强");
             try {
                pj.proceed();
            } catch (Throwable e) {
                //抓捕异常
                e.printStackTrace();
            }
            System.out.println("这是环绕后置增强");
        }
       //异常增强
         @AfterThrowing(value="execution(public * *(..))")
        public void asThorws(){
            System.out.println("这是异常增强");
        }
       //最终增强
         @After(value="execution(public * *(..))")
        public void asAfter(){
            System.out.println("这是最终增强");
        }
    }

         3.1.3  注解的配置文件

    <?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.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
       <!-- 目标对象 -->
       <bean id="aspectimpl" class="cn.happy.impl.AspectjIpml"></bean>
       <!-- 增强类 -->
       <bean id="aspectj" class="cn.happy.aspectj.Aspect"></bean>
       <!-- 扫描整个项目 关联注解类和实现类 -->
       <aop:aspectj-autoproxy />
    
    </beans>

       

         3.1.4   测试类

    package cn.happy.test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import cn.happy.impl.AspectDao;
    
    public class AspectjTest {
        /**
         * 注解测试 */
        public static void main(String[] args) {
            // 解析配置文件
            ApplicationContext ctx = new ClassPathXmlApplicationContext(
                    "applicationContext.xml");
            AspectDao aspect = (AspectDao) ctx.getBean("aspectimpl");
            aspect.add();
            aspect.delete();
        }
    }

          4. Aspectj的XML配置法,其他的基本都一样只要修改Aspectj增强类和配置文件就行了

         4.1 Aspect增强类只需将那些注解消去即可

    package cn.happy.aspectj;
    import org.aspectj.lang.ProceedingJoinPoint;
    
    public class Aspect {
        //前置增强
        public void asBefore(){
            System.out.println("这是前置增强");
        }
        //后置增强
        public void asAfterReturning(){
            
            System.out.println("这是后置增强");
        }
      //环绕增强
        public void asAround(ProceedingJoinPoint pj){
            System.out.println("这是环绕前置增强");
            try {
                pj.proceed();
            } catch (Throwable e) {
                //抓捕异常
                e.printStackTrace();
            }
            System.out.println("这是环绕后置增强");
        }
      //异常增强
        public void asThorws(){
            
            System.out.println("这是异常增强");
        }
      //最终增强
        public void asAfter(){
            
            System.out.println("这是最终增强");
        }
    }

          4.2 XML的配置文件会稍微会复杂一点,但大致的还是跟对原始的经典aop实现方式相同

    <?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.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
       <!-- 目标对象 -->
       <bean id="aspectimpl" class="cn.happy.impl.AspectjIpml"></bean>
       <!-- 增强类 -->
       <bean id="aspectj" class="cn.happy.aspectj.Aspect"></bean>
       <!-- Aspectj的XML配置文件 -->
       <aop:config>
        <aop:pointcut expression="execution(public * *(..))" id="pointcut"/>
        <aop:aspect ref="aspectj">
         <aop:before method="asBefore" pointcut-ref="pointcut"/>
         <aop:after-returning method="asAfterReturning" pointcut-ref="pointcut"/>
         <aop:after-returning method="asAround(org.aspectj.lang.ProceedingJoinPoint)" pointcut-ref="pointcut"/>
         </aop:aspect>
       </aop:config>
    </beans>

          

          好了,这就是AOP(面向切面编程)的四种实现方式了。希望你们看了之后能让你们对AOP面向切面编程思想有更深的了解。

  • 相关阅读:
    mysql存储过程 --游标的使用 取每行记录 (多字段)
    mysql rowid实现
    redis进程守护脚本
    CF1042B 【Vitamins】(去重,状压搜索)
    CF1042A 【Benches】(优先队列)
    魔板 Magic Squares(广搜,状态转化)
    解方程(hash,秦九韶算法)
    noip模拟赛 动态仙人掌(并查集,贪心)
    (暴力碾标算)NOIP模拟赛 宗教仪式
    牛客网NOIP赛前集训营-提高组18/9/9 A-中位数
  • 原文地址:https://www.cnblogs.com/bdpsc/p/5955494.html
Copyright © 2011-2022 走看看