zoukankan      html  css  js  c++  java
  • Spring的AOP

    AOP(aspect oriented <['orɪɛntɪd]导向> Programming,面向切面编程)

    AOP把一个业务流程分成几部分,例如权限检查、事务处理、日志记录,每个部分独立处理,然后把它们组装成完整的业务流程

    aop小例子:

    package com.aop;
    
    public interface IAopService {
        public void withAop() throws Exception;
        public void withoutAop() throws Exception;
    }
    
    package com.aop;
    
    import javax.security.auth.login.AccountException;
    
    public class AopServiceImpl implements IAopService {
    
        private String name;
        public void withAop() throws Exception {
            System.out.println("有AOP的函数运行。name:"+name);
            if(name.trim().length()==0){
                throw new AccountException("name属性不能为空");
            }
        }
    
        public void withoutAop() throws Exception {
            System.out.println("没有AOP的函数运行。");
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    }
    
    
    package com.aop;
    
    import java.lang.reflect.Method;
    
    import org.springframework.aop.AfterReturningAdvice;
    
    public class MethodAfterInterceptor implements AfterReturningAdvice{
    
        public void afterReturning(Object value, Method method, Object[] arg2,
                Object instance) throws Throwable {
            System.out.println("方法"+method.getName()+"运行完毕,返回值为:"+value);
        }
    
    }
    
    package com.aop;
    
    import java.lang.reflect.Method;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    public class MethodBeforeInterceptor implements MethodBeforeAdvice{
    
        public void before(Method method, Object[] arg, Object instance)
                throws Throwable {
            System.out.println("即将要执行的方法:"+method.getName());
            if(instance instanceof AopServiceImpl){
                String name=((AopServiceImpl)instance).getName();
                if(name==null){
                    throw new NullPointerException("name属性不能为null");
                }
            }
        }
    
    }
    
    
    package com.aop;
    
    import java.lang.reflect.Method;
    
    import javax.security.auth.login.AccountException;
    
    import org.springframework.aop.ThrowsAdvice;
    
    public class ThrowsInterceptor implements ThrowsAdvice{
        public void afterThrowing(Method method,Object[] args,Object instance,AccountException ex) throws Throwable{
            System.out.println("方法"+method.getName()+"抛出了异常: "+ex);
        }
        public void afterThrowing(NullPointerException ex) throws Throwable{
            System.out.println("抛出了异常: "+ex);
        }
    }
    
    
    package com.Test;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.aop.IAopService;
    
    public class AopRun {
        @Test
        public static void main(String[]args) throws Exception{
            ApplicationContext conte=new ClassPathXmlApplicationContext("applicationContext.xml");
            IAopService hello=(IAopService)conte.getBean("aopService");
            hello.withAop();
            
        }
    
    }
    
    
    <?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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
        
        <bean id="aopMethodBeforeInterceptor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
            <property name="advice">
                <bean class="com.aop.MethodBeforeInterceptor"></bean>
            </property>
            <property name="mappedName" value="withAop"></property>
        </bean>
        
        <bean id="aopMethodAfterInterceptor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
            <property name="advice">
                <bean class="com.aop.MethodAfterInterceptor">
                </bean>
            </property>
            <property name="mappedName" value="withAop"></property>
        </bean>
        <bean id="aopThrowsInterceptor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
            <property name="advice">
                <bean class="com.aop.ThrowsInterceptor"></bean>
            </property>
            <property name="mappedName" value="withAop"></property>
        </bean>
        
        <!--  Service对象,安装到ProxyFactoryBean对象中 -->
        <bean id="aopService" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="interceptorNames">
                <list>
                    <value>aopMethodBeforeInterceptor</value>
                    <value>aopMethodAfterInterceptor</value>
                    <value>aopThrowsInterceptor</value>
                </list>
            </property>
            <property name="target">
                <bean class="com.aop.AopServiceImpl">
                    <property name="name" value="sss"></property>
                </bean>
            </property>
        </bean>
    </beans>
    View Code

    拦截器与Filter的区别

    Spring的拦截器与Servlet的Filter有相似之处,比如二者都是AOP编程思想的体现,能实现权限检查、日志记录等等。不同的是:

    1、使用范围不同:Filter是Servlet规范规定的,只能用于Web程序中。而拦截器既可以用于Web程序,也可以用于Application、Swing程序中

    2、规范不同:Filter实在Servlet规范中定义的,是Servlet容器支持的。而拦截器是Spring容器内的,是Spring框架支持的。

    3、使用的资源不同:同其他的代码块一样,拦截器也是一个Spring组件,归Spring管理,配置在Spring文件中,因此能使用Spring里的任何资源、对象,例如Service对象、数据源、事务管理等,通过IoC注入到拦截器即可,Filter不能

    4、深度不同:Filter只在Servlet前后起作用。而拦截器能够深入到方法前后、异常抛出前后等等,因此拦截器具有更大的弹性。所以在Spring构架的程序中,要优先使用拦截器。

    AOP的相关概念

    1、切面 Aspect:在本例中,方法withAop()、withoutAop()中都有一些代码。虽然只是一些输出语句,但是在真实的程序中这里应该是一些有意义的代码(如读写数据库、权限检查、异常情况记录等等)。这些代码可以看做事AOP中的切面(Aspect)。可以将切面理解成模块

    2、通知Advisor:本例的三个拦截器都是实现自某个Advise接口。从类名上看就知道三个拦截器就是AOP中的通知(Adcisor)。一旦Spring复合条件,就会派发出通知。与生活中的通知不同的是,Spring的通知是带有执行代码的,能实现某种功能。

    3、切入点Pointcut:在配置拦截器的时候,XML只配置了withAop()方法使用拦截器,而withoutAop()方法没有配置拦截器。这种配置时借助于org.springframework.aop.support.NameMathMethodPointcutAdvisor完成的。从类名称上看,这是一个切入点(Pointcut)。该类对象能够配置哪些方法使用拦截器,从哪个地方切进去。配置的时候可以使用通配符。该类名上也带有Adcisor是因为它是用通知(Advisor)实现的

    简单地说,切入点负责往什么地方插入代码,而通知负责插入什么代码

    4、切入点配置方式:Spring提供灵活的切入点配置方式,例如使用正则表达式。

    <bean id="aopMethodAfterInterceptor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice">
                <bean class="com.aop.MethodAfterInterceptor">
                </bean>
            </property>
            <property name="patterns">
                <list>
                    <value>.*withAop</value>
                    <value>.*like.*</value>
                </list>
            </property>
        </bean>
    
    
    package com.Test;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.aop.IAopService;
    
    public class AopRun {
        @Test
        public static void main(String[]args) throws Exception{
            ApplicationContext conte=new ClassPathXmlApplicationContext("applicationContext.xml");
            IAopService hello=(IAopService)conte.getBean("aopService");
            hello.withAop();
            hello.youlike();
            
        }
        
        public static void slikeme(){
            System.out.println("这是slikeme方法");
        }
    
    }
    
    其他不是很需要讲解的地方加了slikeme方法
    View Code

    注意:正则有点怪。(好像前面必须是.*)

    AOP的代理模式

    代理模式是Spring中常用的设计模式。Spring提供了几个常用的代理类,例如普通的代理类、事务处理类等等。

    1、ProxyFactoryBean代理工厂对象

    org.springframework.aop.framework.ProxyFactory.这是spring内置的代理类,引入了一个中间层,能够创建不同类型的对象。利用它可以实现任何形式的AOP

    2、TransactionProxyFactoryBean事务代理工厂对象

    TransactionProxyFactoryBean,是ProxyFactoryBean的子类,常用在数据库编程上。Spring、利用TransactionProxyFactoryBean对事务进行管理,在指定方法前利用AOP连接数据库并开启事务,然后在指定的方法返回后利用AOP提交事务并断开数据库。

    <bean id=:petStoreTarget" class="......" ><!--代码实例-->
        <property name="accountDao">
            <ref bean="accountDao" />
        <property>  <!--设置DAO引用-->
    </bean>
    <bean id="petStore" class="org.springframework.interceptor.TransactionProxyFactoryBean"><!--安装事务管理bean-->
         <property name="transactionManager" ref="transactionManager" /><!--事务管理Bean-->
        <property name="target" ref="petStoreTaeget" /><!--安装到该bean-->
        <property name="transactionAttributes"><!--方法名配置-->
            <props>
                 <prop key="insert">PROPAGATION_REQUIRED</prop>
                 <prop key="update*">PROPAGATION_REQUIRED</prop>
                 <prop key="*">PROPAGATION_REQUIRED,readoOnly</prop>
            </props>
        </property>
    </beans>

     注意:使用spring的aop的时候将ProxyFactoryBean只能转化成为接口类型。而不是它的实现类。

  • 相关阅读:
    模块
    python运算符与表达式
    subShell与代码块
    参数展开与特殊字符
    变量和参数
    shelll Test
    Cypher查询语言--Neo4j 入门 (一)
    那些争议最大的编程观点
    大型网站架构不得不考虑的10个问题
    大型网站架构演变
  • 原文地址:https://www.cnblogs.com/aigeileshei/p/5466456.html
Copyright © 2011-2022 走看看