【转】Spring的AOP面向切面编程

本文介绍AOP的概念及其在Spring框架中的应用,通过具体示例展示了如何实现日志记录和权限控制等功能。

一、AOP的概述

AOP是基于反射与动态代理的实现,java有反射的中间层,让AOP的实现更加简单,而C++想实现相比会较为困难。

AOP为:(aspect oriented programming),面向切面编程。是对OOP的补充,弥补OOP的不足。
作用:在不修改源码的前提下,给项目增加新的公共功能,如:权限,日志,事务(数据库中同时成功或同时失败的操作的集合)。

二、AOP的组成要数

分别有以下几点:

  • advice:通知。即新增的功能。比如写日志。
  • target:目标。通知加入的目标类
  • joinpoint:切点。通知加入的目标类的具体位置
  • pointcut:切线。所有切点的集合
  • aspect:切面。切线+通知
  • weaving:动词。织入。
  • introduction:在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段。

三、AOP原理

基于设计模式之“代理模式”。agent/proxy。
代码实现上面分为:静态代理 和 动态代理。
代理模式的原理:代理对象和被代理对象实现同样的业务接口,由代理对象代替其完成业务行为,并增加“附加行为”。

例如:我想去动物园买票,传统方式是直接到动物园门口购票。而现在我可以找个人代替我买票,那个人就是代理人,而他也要向我索取金钱(成本+代理费。。)之类的附加行为,就是代理业务。
而现在的AOP就是那个代理人,替我们去做事的代理人。

注意:spring实现aop采用的”动态代理”的方式。动态代理意思是,去帮你做事的代理对象不是固定的,是用Spring动态创建的

四、Spring对AOP的支持

Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。

AOP通知日志的简单实例,创建一个User接口,具有登陆与注册两个方法:

<span style="color:#000000"><code><span style="color:#000088 !important">public</span> <span style="color:#000088 !important">interface</span> User {
    <span style="color:#000088 !important">void</span> login();
    <span style="color:#000088 !important">void</span> register();
}</code></span>

创建一个代理对象UserImpl,实现User接口:

<span style="color:#000000"><code><span style="color:#000088 !important">public</span> <span style="color:#000088 !important">class</span> <span style="color:#4f4f4f !important">UserImpl</span> <span style="color:#000088 !important">implements</span> <span style="color:#4f4f4f !important">User</span> {

    <span style="color:#000088 !important">private</span> String role;

    <span style="color:#000088 !important">public</span> String <span style="color:#009900 !important">getRole</span>() {
        <span style="color:#000088 !important">return</span> role;
    }

    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">setRole</span>(String role) {
        <span style="color:#000088 !important">this</span>.role = role;
    }

    <span style="color:#9b859d !important">@Override</span>
    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">login</span>() {
        System.out.println(<span style="color:#009900 !important">"完成登录的业务方法!"</span>);
    }

    <span style="color:#9b859d !important">@Override</span>
    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">register</span>()  {
        System.out.println(<span style="color:#009900 !important">"完成注册的业务方法!"</span>);
    }
}</code></span>

创建一个通知类对象MyAdvice:

<span style="color:#000000"><code><span style="color:#000088 !important">public</span> <span style="color:#000088 !important">class</span> MyAdvice {

    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">beforelog</span>()
    {
        System.<span style="color:#000088 !important">out</span>.println(<span style="color:#009900 !important">"这是前置通知的日志。"</span>);
    }

    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">afterlog</span>()
    {
        System.<span style="color:#000088 !important">out</span>.println(<span style="color:#009900 !important">"这是后置通知的日志。"</span>);
    }

    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">aroundlog</span>(ProceedingJoinPoint p) throws Throwable
    {
        System.<span style="color:#000088 !important">out</span>.println(<span style="color:#009900 !important">"环绕前的日志!"</span>);
        p.proceed();  <span style="color:#880000 !important"><em>//让原来的业务方法执行!</em></span>
        System.<span style="color:#000088 !important">out</span>.println(<span style="color:#009900 !important">"环绕后的日志!"</span>);
    }


    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">throwlog</span>()
    {
        System.<span style="color:#000088 !important">out</span>.println(<span style="color:#009900 !important">"这是异常通知的日志"</span>);
    }
}</code></span>

在applicationContext.xml文件配置头部:

<span style="color:#000000"><code><beans xmlns=<span style="color:#009900 !important">"http://www.springframework.org/schema/beans"</span>
    xmlns:xsi=<span style="color:#009900 !important">"http://www.w3.org/2001/XMLSchema-instance"</span>
    xmlns:aop=<span style="color:#009900 !important">"http://www.springframework.org/schema/aop"</span>
    xsi:schemaLocation=<span style="color:#009900 !important">"http://www.springframework.org/schema/beans</span>
    http:<span style="color:#880000 !important"><em>//www.springframework.org/schema/beans/spring-beans-3.0.xsd</em></span>
    http:<span style="color:#880000 !important"><em>//www.springframework.org/schema/aop</em></span>
    http:<span style="color:#880000 !important"><em>//www.springframework.org/schema/aop/spring-aop-3.0.xsd"></em></span></code></span>

接着配置其代理对象,和通知类对象及织入关系

<span style="color:#000000"><code>    <span style="color:#880000 !important"><em><!-- 创建1个业务实现类对象 --></em></span>
    <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">bean</span> <span style="color:#4f4f4f !important">id</span>=<span style="color:#009900 !important">"user"</span> <span style="color:#4f4f4f !important">class</span>=<span style="color:#009900 !important">"com.sunsharing.entity.UserImpl"</span>></span>
    <span style="color:#006666 !important"></<span style="color:#4f4f4f !important">bean</span>></span>

    <span style="color:#880000 !important"><em><!--创建1个自定义通知类对象 --></em></span>
    <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">bean</span> <span style="color:#4f4f4f !important">id</span>=<span style="color:#009900 !important">"myadvice"</span> <span style="color:#4f4f4f !important">class</span>=<span style="color:#009900 !important">"com.sunsharing.entity.MyAdvice"</span>></span>

    <span style="color:#006666 !important"></<span style="color:#4f4f4f !important">bean</span>></span>

    <span style="color:#880000 !important"><em><!-- 配置 织入关系 --></em></span>
    <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">aop:config</span>></span>
    <span style="color:#880000 !important"><em><!-- 定义1条切线 --></em></span>
      <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">aop:pointcut</span> <span style="color:#4f4f4f !important">expression</span>=<span style="color:#009900 !important">"execution(* com.sunsharing.entity.UserImpl.login(..))"</span> <span style="color:#4f4f4f !important">id</span>=<span style="color:#009900 !important">"mypc"</span>/></span> <span style="color:#880000 !important"><em><!--这里监听的是login方法--></em></span>
      <span style="color:#880000 !important"><em><!--配置切面 ,引用自定义通知对象--></em></span>
      <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">aop:aspect</span> <span style="color:#4f4f4f !important">ref</span>=<span style="color:#009900 !important">"myadvice"</span>></span>
         <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">aop:before</span> <span style="color:#4f4f4f !important">method</span>=<span style="color:#009900 !important">"beforelog"</span> <span style="color:#4f4f4f !important">pointcut-ref</span>=<span style="color:#009900 !important">"mypc"</span>/></span> 

         <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">aop:after</span> <span style="color:#4f4f4f !important">method</span>=<span style="color:#009900 !important">"afterlog"</span> <span style="color:#4f4f4f !important">pointcut-ref</span>=<span style="color:#009900 !important">"mypc"</span>/></span>

         <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">aop:around</span> <span style="color:#4f4f4f !important">method</span>=<span style="color:#009900 !important">"aroundlog"</span> <span style="color:#4f4f4f !important">pointcut-ref</span>=<span style="color:#009900 !important">"mypc"</span>/></span>

         <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">aop:after-throwing</span> <span style="color:#4f4f4f !important">method</span>=<span style="color:#009900 !important">"throwlog"</span> <span style="color:#4f4f4f !important">pointcut-ref</span>=<span style="color:#009900 !important">"mypc"</span>/></span>
      <span style="color:#006666 !important"></<span style="color:#4f4f4f !important">aop:aspect</span>></span>
    <span style="color:#006666 !important"></<span style="color:#4f4f4f !important">aop:config</span>></span></code></span>

最后,在TestUser测试类中进行日志测试:

<span style="color:#000000"><code class="language-java"><span style="color:#000088 !important">import</span> com.sunsharing.entity.User;

<span style="color:#000088 !important">import</span> org.springframework.beans.factory.BeanFactory;
<span style="color:#000088 !important">import</span> org.springframework.context.support.ClassPathXmlApplicationContext;

<span style="color:#000088 !important">public</span> <span style="color:#000088 !important">class</span> <span style="color:#4f4f4f !important">TestUser</span> {

    <span style="color:#9b859d !important">@org</span>.junit.Test
    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">test</span>() {
        BeanFactory fac = <span style="color:#000088 !important">new</span> ClassPathXmlApplicationContext(<span style="color:#009900 !important">"applicationContext.xml"</span>);
        User user = (User) fac.getBean(<span style="color:#009900 !important">"user"</span>);
        user.login();
    }
}</code></span>

输出结果:
这里写图片描述
其中还有个抛出异常的日志监听,在register方法抛出个自定义异常试试。

<span style="color:#000000"><code><span style="color:#9b859d !important">@Override</span>
    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">register</span>()  {
        <span style="color:#000088 !important">throw</span> <span style="color:#000088 !important">new</span> RuntimeException(<span style="color:#009900 !important">"这是注册的异常!"</span>);
        <span style="color:#880000 !important"><em>//System.out.println("完成注册的业务方法!");</em></span>
    }</code></span>

然后把applicationContext中的监听方法改为rigister

<span style="color:#000000"><code><span style="color:#006666 !important"><<span style="color:#4f4f4f !important">aop:pointcut</span> <span style="color:#4f4f4f !important">expression</span>=<span style="color:#009900 !important">"execution(* com.sunsharing.entity.UserImpl.register(..))"</span> <span style="color:#4f4f4f !important">id</span>=<span style="color:#009900 !important">"mypc"</span>/></span></code></span>
  •  

测试类中运行后,输出的结果为:
这里写图片描述
以上是日志功能的实现,接下来再讲个权限功能的实现

五、AOP的权限功能

沿用以上的例子,加个周四无法注册的权限控制。
创建一个MyRegAdvice的自定义通知类:

<span style="color:#000000"><code><span style="color:#000088 !important">package</span> com.sunsharing.entity;

<span style="color:#000088 !important">import</span> java.util.Calendar;

<span style="color:#000088 !important">import</span> org.aspectj.lang.ProceedingJoinPoint;

<span style="color:#000088 !important">public</span> <span style="color:#000088 !important">class</span> <span style="color:#4f4f4f !important">MyRegAdvice</span>
{
    <span style="color:#880000 !important"><em>//这是环绕通知</em></span>
    <span style="color:#000088 !important">public</span> <span style="color:#000088 !important">void</span> <span style="color:#009900 !important">checkday</span>(ProceedingJoinPoint p) <span style="color:#000088 !important">throws</span> Throwable
    {
        Calendar c = Calendar.getInstance();

        <span style="color:#000088 !important">int</span> day = c.get(Calendar.DAY_OF_WEEK);
        <span style="color:#000088 !important">if</span>(day==<span style="color:#006666 !important">5</span>)<span style="color:#880000 !important"><em>//周日是第一天为1,因此周四是5,亲测!</em></span>
        {
            System.out.println(<span style="color:#009900 !important">"周四无法注册!"</span>);
            <span style="color:#000088 !important">return</span>;
        }

        p.proceed(); <span style="color:#880000 !important"><em>//其他情况,允许往前走。</em></span>
    }
}</code></span>

创建一个applicationContext_register.xml配置文件:

<span style="color:#000000"><code><span style="color:#006666 !important"><<span style="color:#4f4f4f !important">beans</span> <span style="color:#4f4f4f !important">xmlns</span>=<span style="color:#009900 !important">"http://www.springframework.org/schema/beans"</span>
    <span style="color:#4f4f4f !important">xmlns:xsi</span>=<span style="color:#009900 !important">"http://www.w3.org/2001/XMLSchema-instance"</span>
    <span style="color:#4f4f4f !important">xmlns:aop</span>=<span style="color:#009900 !important">"http://www.springframework.org/schema/aop"</span>
    <span style="color:#4f4f4f !important">xsi:schemaLocation</span>=<span style="color:#009900 !important">"http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"</span>></span>

    <span style="color:#880000 !important"><em><!-- 创建1个业务实现类对象 --></em></span>
    <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">bean</span> <span style="color:#4f4f4f !important">id</span>=<span style="color:#009900 !important">"user"</span> <span style="color:#4f4f4f !important">class</span>=<span style="color:#009900 !important">"com.sunsharing.entity.UserImpl"</span>></span>

    <span style="color:#006666 !important"></<span style="color:#4f4f4f !important">bean</span>></span>

    <span style="color:#880000 !important"><em><!--创建1个自定义通知类对象 --></em></span>
    <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">bean</span> <span style="color:#4f4f4f !important">id</span>=<span style="color:#009900 !important">"myadvice"</span> <span style="color:#4f4f4f !important">class</span>=<span style="color:#009900 !important">"com.sunsharing.entity.MyRegAdvice"</span>></span>

    <span style="color:#006666 !important"></<span style="color:#4f4f4f !important">bean</span>></span>

    <span style="color:#880000 !important"><em><!-- 配置 织入关系 --></em></span>
    <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">aop:config</span>></span>
    <span style="color:#880000 !important"><em><!-- 定义1条切线 --></em></span>
      <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">aop:pointcut</span> <span style="color:#4f4f4f !important">expression</span>=<span style="color:#009900 !important">"execution(* com.sunsharing.entity.UserImpl.reg*(..))"</span> <span style="color:#4f4f4f !important">id</span>=<span style="color:#009900 !important">"mypc"</span>/></span>
      <span style="color:#880000 !important"><em><!--配置切面 ,引用自定义通知对象--></em></span>
      <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">aop:aspect</span> <span style="color:#4f4f4f !important">ref</span>=<span style="color:#009900 !important">"myadvice"</span>></span>
        <span style="color:#006666 !important"><<span style="color:#4f4f4f !important">aop:around</span> <span style="color:#4f4f4f !important">method</span>=<span style="color:#009900 !important">"checkday"</span> <span style="color:#4f4f4f !important">pointcut-ref</span>=<span style="color:#009900 !important">"mypc"</span>/></span>
      <span style="color:#006666 !important"></<span style="color:#4f4f4f !important">aop:aspect</span>></span>
    <span style="color:#006666 !important"></<span style="color:#4f4f4f !important">aop:config</span>></span>
<span style="color:#006666 !important"></<span style="color:#4f4f4f !important">beans</span>></span></code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

最后在测试类进行测试,测试类完全不用改动。
输出结果为:
这里写图片描述

内容概要:本文设计了一种基于PLC的全自动洗衣机控制系统内容概要:本文设计了一种,采用三菱FX基于PLC的全自动洗衣机控制系统,采用3U-32MT型PLC作为三菱FX3U核心控制器,替代传统继-32MT电器控制方式,提升了型PLC作为系统的稳定性与自动化核心控制器,替代水平。系统具备传统继电器控制方式高/低水,实现洗衣机工作位选择、柔和过程的自动化控制/标准洗衣模式切换。系统具备高、暂停加衣、低水位选择、手动脱水及和柔和、标准两种蜂鸣提示等功能洗衣模式,支持,通过GX Works2软件编写梯形图程序,实现进洗衣过程中暂停添加水、洗涤、排水衣物,并增加了手动脱水功能和、脱水等工序蜂鸣器提示的自动循环控制功能,提升了使用的,并引入MCGS组便捷性与灵活性态软件实现人机交互界面监控。控制系统通过GX。硬件设计包括 Works2软件进行主电路、PLC接梯形图编程线与关键元,完成了启动、进水器件选型,软件、正反洗涤部分完成I/O分配、排水、脱、逻辑流程规划水等工序的逻辑及各功能模块梯设计,并实现了大形图编程。循环与小循环的嵌; 适合人群:自动化套控制流程。此外、电气工程及相关,还利用MCGS组态软件构建专业本科学生,具备PL了人机交互C基础知识和梯界面,实现对洗衣机形图编程能力的运行状态的监控与操作。整体设计涵盖了初级工程技术人员。硬件选型、; 使用场景及目标:I/O分配、电路接线、程序逻辑设计及组①掌握PLC在态监控等多个方面家电自动化控制中的应用方法;②学习,体现了PLC在工业自动化控制中的高效全自动洗衣机控制系统的性与可靠性。;软硬件设计流程 适合人群:电气;③实践工程、自动化及相关MCGS组态软件与PLC的专业的本科生、初级通信与联调工程技术人员以及从事;④完成PLC控制系统开发毕业设计或工业的学习者;具备控制类项目开发参考一定PLC基础知识。; 阅读和梯形图建议:建议结合三菱编程能力的人员GX Works2仿真更为适宜。; 使用场景及目标:①应用于环境与MCGS组态平台进行程序高校毕业设计或调试与运行验证课程项目,帮助学生掌握PLC控制系统的设计,重点关注I/O分配逻辑、梯形图与实现方法;②为工业自动化领域互锁机制及循环控制结构的设计中类似家电控制系统的开发提供参考方案;③思路,深入理解PL通过实际案例理解C在实际工程项目PLC在电机中的应用全过程。控制、时间循环、互锁保护、手动干预等方面的应用逻辑。; 阅读建议:建议结合三菱GX Works2编程软件和MCGS组态软件同步实践,重点理解梯形图程序中各环节的时序逻辑与互锁机制,关注I/O分配与硬件接线的对应关系,并尝试在仿真环境中调试程序以加深对全自动洗衣机控制流程的理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值