`

Spring aop 原理及各种应用场景

    博客分类:
  • SSIH
 
阅读更多
AOP是Aspect Oriented Programing的简称,面向切面编程。AOP适合于那些具有横切逻辑的应用:如性能监测,访问控制,事务管理、缓存、对象池管理以及日志记录。AOP将这些分散在各个业务逻辑中的代码通过横向切割的方式抽取到一个独立的模块中。AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理和动态代理两大类,其中静态代理是指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;而动态代理则在运行时借助于 JDK 动态代理、CGLIB 等在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。
代理对象的方法 = 增强处理 + 被代理对象的方法
Spring AOP 则采用运行时生成 AOP 代理类,因此无需使用特定编译器进行处理。由于 Spring AOP 需要在每次运行时生成 AOP 代理,因此性能略差一些。

AOP使用场景


AOP用来封装横切关注点,具体可以在下面的场景中使用
Authentication 权限
Caching 缓存
Context passing 内容传递
Error handling 错误处理
Lazy loading 懒加载
Debugging  调试
logging, tracing, profiling and monitoring 记录跟踪 优化 校准
Performance optimization 性能优化
Persistence  持久化
Resource pooling 资源池
Synchronization 同步
Transactions 事务

AOP相关概念

方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的 Advisor或拦截器实现。
连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出
通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice
切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上
引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口
目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO
AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

日志应用:
实现登陆和日志管理(使用Spring AOP

1)LoginService   LogService   TestMain

2)用Spring 管理  LoginService 和 LogService 的对象

3)确定哪些连接点是切入点,在配置文件中

4)将LogService封装为通知

5)将通知植入到切入点

6)客户端调用目标



    <aop:config>
        <aop:pointcut expression="execution(* cn.com.spring.service.impl.*.*(..))" id="myPointcut"/>
        <!--将哪个-->
        <aop:aspect id="dd" ref="logService">
          <aop:before method="log" pointcut-ref="myPointcut"/>
        </aop:aspect>
    </aop:config>

execution(* * cn.com.spring.service.impl.*.*(..))

1)* 所有的修饰符

2)* 所有的返回类型

3)* 所有的类名

4)* 所有的方法名

5)* ..所有的参数名


1.ILoginService.java


    package cn.com.spring.service;

    public interface ILoginService {
        public boolean login(String userName, String password);
    }

2.LoginServiceImpl.java


    package cn.com.spring.service.impl;

    import cn.com.spring.service.ILoginService;

    public class LoginServiceImpl implements ILoginService {

        public boolean login(String userName, String password) {
            System.out.println("login:" + userName + "," + password);
            return true;
        }

    }

3.ILogService.java


    package cn.com.spring.service;

    import org.aspectj.lang.JoinPoint;

    public interface ILogService {
        //无参的日志方法
        public void log();
        //有参的日志方法
        public void logArg(JoinPoint point);
        //有参有返回值的方法
        public void logArgAndReturn(JoinPoint point,Object returnObj);
    }


4.LogServiceImpl.java


    package cn.com.spring.service.impl;

    import org.aspectj.lang.JoinPoint;

    import cn.com.spring.service.ILogService;

    public class LogServiceImpl implements ILogService {

        @Override
        public void log() {
            System.out.println("*************Log*******************");
        }
       
        //有参无返回值的方法
        public void logArg(JoinPoint point) {
            //此方法返回的是一个数组,数组中包括request以及ActionCofig等类对象
            Object[] args = point.getArgs();
            System.out.println("目标参数列表:");
            if (args != null) {
                for (Object obj : args) {
                    System.out.println(obj + ",");
                }
                System.out.println();
            }
        }

        //有参并有返回值的方法
        public void logArgAndReturn(JoinPoint point, Object returnObj) {
            //此方法返回的是一个数组,数组中包括request以及ActionCofig等类对象
            Object[] args = point.getArgs();
            System.out.println("目标参数列表:");
            if (args != null) {
                for (Object obj : args) {
                    System.out.println(obj + ",");
                }
                System.out.println();
                System.out.println("执行结果是:" + returnObj);
            }
        }
    }

5.applicationContext.java


    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:aop="http://www.springframework.org/schema/aop" 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-2.5.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

        <bean id="logService" class="cn.com.spring.service.impl.LogServiceImpl"></bean>
        <bean id="loginService" class="cn.com.spring.service.impl.LoginServiceImpl"></bean>

        <aop:config>
            <!-- 切入点 -->
            <aop:pointcut
                expression="execution(* cn.com.spring.service.impl.LoginServiceImpl.*(..))"
                id="myPointcut" />
            <!-- 切面: 将哪个对象中的哪个方法,织入到哪个切入点 -->
            <aop:aspect id="dd" ref="logService">
                <!-- 前置通知
                <aop:before method="log" pointcut-ref="myPointcut" />
                <aop:after method="logArg" pointcut-ref="myPointcut">
        -->
                <aop:after-returning method="logArgAndReturn" returning="returnObj" pointcut-ref="myPointcut"/>
            </aop:aspect>
        </aop:config>
    </beans>

6.TestMain.java


    public class TestMain {
    public static void testSpringAOP(){
            ApplicationContext ctx = new ClassPathXmlApplicationContext("app*.xml");
           
            ILoginService loginService = (ILoginService)ctx.getBean("loginService");
            loginService.login("zhangsan", "12344");
    }
    public static void main(String[] args) {
    testSpringAOP();
    }
    }

7.输出结果:

    login:zhangsan,12344
    目标参数列表:
    zhangsan,
    12344,

    执行结果是:true

解析:1.先调用了login()方法System.out.println("login:" + userName + "," + password);

     2.再调用了logArgAndReturn()方法输出了日志,并且返回了login()方法是否成功


    System.out.println("目标参数列表:");
            if (args != null) {
                for (Object obj : args) {
                    System.out.println(obj + ",");
                }
                System.out.println();
                System.out.println("执行结果是:" + returnObj);
            }

权限控制
首先定义一个用户:
Java代码  收藏代码

    public class User { 
        private String username; 
     
        public String getUsername() { 
            return username; 
        } 
        public void setUsername(String username) { 
            this.username = username; 
        } 
    } 


用户有三种人:未注册用户,注册用户,与管理员
注册用户可以可以发表,回复帖子
管理员除了可以发表,回复帖子,还可以删除帖子!
下面定义TestCommunity接口:
Java代码  收藏代码

    public interface TestCommunity { 
      public void answerTopic(); 
      public void deleteTopic(); 
    } 



实现上面接口的TestCommunityImpl类:
Java代码  收藏代码

    public class TestCommunityImpl implements TestCommunity { 
        //注册用户与管理员拥有的功能 
        public void answerTopic() { 
            System.out.println("可以发表,回复帖子"); 
        } 
        //管理员拥有的功能 
        public void deleteTopic() { 
            System.out.println("可以删除帖子!"); 
        } 
    } 



下一步,建立一下依赖注入的实现类TestResultImpl:
Java代码  收藏代码

    public class TestResultImpl { 
        private TestCommunity test; 
     
        public void setTest(TestCommunity test) { 
            this.test = test; 
        }    
         public void answerTopic() 
         { 
             test.answerTopic(); 
         } 
          public void deleteTopic() 
          { 
              test.deleteTopic(); 
          } 
    } 



接下来,就是最重要的一个类,拦截器,Around处理类型的,类TestAuthorityInterceptor:
Java代码  收藏代码

    import org.aopalliance.intercept.MethodInterceptor; 
    import org.aopalliance.intercept.MethodInvocation; 
     
    //创建Around处理应该实现MethodInterceptor接口 
    public class TestAuthorityInterceptor implements MethodInterceptor { 
        private User user; 
     
        public User getUser() { 
            return user; 
        } 
        public void setUser(User user) { 
            this.user = user; 
        } 
     
        // invoke方法返回调用的结果 
        public Object invoke(MethodInvocation invocation) throws Throwable { 
            String methodName = invocation.getMethod().getName(); 
     
            if (user.getUsername().equals("unRegistedUser")) { 
                System.out.println("你的身份是未注册用户,没有权限回复,删除帖子!"); 
                return null; 
            } 
            if ((user.getUsername().equals("user")) 
                    && (methodName.equals("deleteTopic"))) { 
                System.out.println("你的身份是注册用户,没有权限删除帖子"); 
                return null; 
            } 
            // proceed()方法对连接点的整个拦截器链起作用,拦截器链中的每个拦截器都执行该方法,并返回它的返回值 
            return invocation.proceed(); 
        } 
     
    } 



配置文件:
Java代码  收藏代码

    <?xml version="1.0" encoding="UTF-8"?> 
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> 
    <beans> 
        <bean id="authTarget" class="org.test.lighter.TestCommunityImpl" /> 
     
        <!-- 其中的username可以写为admin,user,和unRegistedUser --> 
        <bean id="user" class="org.test.lighter.User"> 
            <property name="username" value="user" /> 
        </bean> 
     
        <!-- 配置拦截器 --> 
        <bean id="TestAuthorityInterceptor" 
            class="org.test.lighter.TestAuthorityInterceptor"> 
            <property name="user" ref="user" /> 
        </bean> 
     
        <!-- 配置代理工厂bean --> 
       <bean id="service" 
            class="org.springframework.aop.framework.ProxyFactoryBean"> 
            <property name="proxyInterfaces"> 
                <value>org.test.lighter.TestCommunity</value> 
            </property> 
            <property name="target" ref="authTarget"/> 
            <property name="interceptorNames"> 
                <list> 
                    <value>TestAuthorityInterceptor</value> 
                </list> 
            </property> 
        </bean> 
     

        <bean id="testResult" class="org.test.lighter.TestResultImpl"> 
            <property name="test" ref="service" /> 
        </bean> 
    </beans> 



再写一个执行文件BeanTest:
Java代码  收藏代码

    import org.springframework.context.ApplicationContext; 
    import org.springframework.context.support.FileSystemXmlApplicationContext; 
     
    public class BeanTest { 
      public static void main(String[] args) throws Exception 
      { 
          ApplicationContext ctx = new FileSystemXmlApplicationContext("src/bean.xml"); 
          TestResultImpl test = (TestResultImpl)ctx.getBean("testResult"); 
          test.answerTopic(); 
          test.deleteTopic(); 
      } 
    } 


mark from http://blog.csdn.net/sd0902/article/details/8393770
http://lighter.iteye.com/blog/42673
分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    Springaop原理及各种应用场景

    Spring AOP的应用场景广泛,包括但不限于: 1. Authentication:权限控制,确保只有经过认证的用户才能访问特定资源。 2. Caching:缓存,提高数据访问速度,减少数据库交互。 3. Context passing:内容传递,如在...

    反射实现 AOP 动态代理模式(Spring AOP 的实现原理)

    因此,在实际开发中,需要根据应用场景的性能要求和维护需求,权衡是否使用动态代理。 总之,AOP通过提供一种新的角度来解决OO编程中存在的问题,使得我们能够在保持业务逻辑清晰的同时,增加额外的通用功能。利用...

    Spring AOP实现机制

    Spring AOP的应用场景 - **日志记录**:在方法调用前后记录操作信息。 - **事务管理**:自动进行事务的开启、提交、回滚等操作。 - **权限控制**:在访问敏感资源前进行权限检查。 - **性能监控**:记录方法执行...

    SpringAOP的实现机制(底层原理)、应用场景等详解,模拟过程的实例

    通过学习它们的原理和实际应用,您将能够更好地理解和利用Spring AOP来提高您的应用程序的可维护性和可扩展性。 内容亮点: JDK动态代理: 我们将详细介绍JDK动态代理的概念和工作原理。您将了解如何使用Java的...

    spring AOP的运用

    实际应用中,Spring AOP常用于以下场景: 1. 事务管理:使用`@Transactional`注解,可以声明式地管理事务,无需手动编写事务控制代码。 2. 日志记录:在关键方法前、后插入日志记录通知,便于追踪程序执行过程。 3. ...

    springAOP 4个jar包

    Spring AOP是Spring框架的重要组成部分,它提供了面向切面编程的能力,使得开发者可以在不修改源...在实际应用中,Spring AOP常用于日志记录、事务管理、性能监控等多种场景,极大地提高了代码的可维护性和可复用性。

    第3章 Spring AOP.ppt

    【应用场景】 AOP在企业级应用中广泛应用于事务管理、权限控制、日志记录、性能监控等方面。通过AOP,开发者可以将这些通用功能抽取成切面,然后在合适的时候(切点)插入到业务逻辑中,使得业务代码更加简洁,专注...

    SPRING AOP详细培训视频

    6. 实践示例,可能包括事务管理、日志记录等实际应用场景的AOP实现。 通过这个视频教程,学习者可以深入了解Spring AOP的工作原理,并学会如何在实际项目中有效利用AOP来简化代码和提高代码复用。

    Spring AOP学习资料(pdf)

    #### 五、Spring AOP 的应用场景 Spring AOP广泛应用于以下场景: - **日志记录**:自动记录方法调用的日志信息。 - **性能监控**:监测方法执行的时间和资源消耗。 - **安全控制**:检查方法调用的安全权限。 - *...

    Spring AOP的底层实现技术

    8. **AOP的应用场景** AOP在许多场景下都非常有用,如事务管理、日志记录、性能统计、权限控制等。通过AOP,我们可以将这些通用的、分布在整个系统中的功能进行抽象和集中处理,提高代码的可维护性和复用性。 9. *...

    SpringAOP切面实例讲解及应用场景(通俗易懂)

    在实际应用中,Spring AOP 切面可以用于各种场景,比如: - **日志记录**:在方法调用前后记录操作日志,便于追踪程序运行状态。 - **事务管理**:在方法执行前后自动开始和提交/回滚数据库事务,确保数据一致性。 ...

    SpringAop学习笔记以及实现Demo

    本资料包中的四个Demo分别展示了Spring AOP的四种不同应用场景: 1. **经典代理模式Demo**:演示了如何通过CGLIB代理实现方法的拦截,以及在方法调用前后执行自定义操作。 2. **基于注解的AOP Demo**:展示了如何...

    javaXML方式实现SpringAop编程(源码+jar包)

    同时,你也可以运行这些示例,观察控制台输出,进一步熟悉AOP的应用场景。 总结,Spring AOP通过XML配置提供了强大的面向切面编程能力,使我们能够灵活地管理横切关注点,提高代码的可读性和可维护性。通过学习和...

    Spring AOP简单模拟

    **Spring AOP 简单模拟** 在Java开发中,Spring框架因其强大的功能和灵活性而被广泛应用,其中Spring AOP...在实际项目中,Spring AOP常用于日志记录、事务管理、性能监控等场景,是现代企业级应用不可或缺的一部分。

    spring-aop实例demo

    通过深入理解Spring AOP的原理和实践,开发者能够更好地掌握这一强大的设计模式,并将其有效地应用于实际项目中。在实际开发中,我们还需要考虑如何合理划分切面,避免切面之间的冲突,以及如何优化切点表达式以提高...

    通过动态代理模拟Spring AOP

    5. **应用场景:** - 日志记录:在方法调用前后记录日志,无需在每个方法中手动插入日志代码。 - 性能监控:计算方法的执行时间,用于性能分析。 - 事务管理:在方法调用前开启事务,调用后提交或回滚事务。 总...

    Spring AOP 实例

    **Spring AOP 实例** Spring AOP(面向切面编程)是Spring框架的重要组成部分,它允许程序员在不修改源代码的情况下,对程序的行为进行统一...以上实例展示了AOP在实际场景中的应用,帮助理解其工作原理和使用方式。

    spring2-aop.pdf

    ##### 5.4 Spring 中的 AOP 实现及应用 - **Spring AOP 实现**:Spring 使用代理模式实现 AOP 功能,支持基于接口的动态代理和 CGLIB 字节码生成库。 - **Spring AOP 对 AspectJ 的支持**:Spring 允许使用 AspectJ ...

    spring_aop.rar_spring_aop

    在"spring_aop.rar_spring_aop"这个实例工程中,可能包含了两个部分,"spring-aop-1"和"spring-aop-2",它们可能分别展示了不同的AOP应用场景或者使用策略。例如: - "spring-aop-1"可能是一个基础的AOP示例,演示...

    Spring AOP介绍及源码分析

    在实际开发中,AOP的应用场景广泛,例如: 1. **日志记录**:在方法调用前后记录日志,无需在每个业务方法中手动添加日志代码。 2. **事务管理**:通过统一的事务策略管理数据库事务,避免在每个操作数据库的方法中...

Global site tag (gtag.js) - Google Analytics