• [原]spring学习笔记9.3Spring对Aop的支持配置文件的方式


    代码参见dynamic-proxy-AOP2
    基于配置文件的方式的好处在于所谓的分层.所以号称应该推荐使用这个方法
    随便了.代码重新贴一次吧.
    1.UserManager接口
     1package com.zyl.proxy;
     2
     3public interface UserManager {
     4    
     5    public void addUser(String name,String password);
     6    
     7    public void delUser(String id);
     8    
     9    public void modifyUser(int id, String name, String password);
    10    
    11}
    2.UserManagerImpl(UserManager的实现类)
     1package com.zyl.proxy;
     2
     3public class UserManagerImpl implements UserManager {
     4
     5
     6    public void addUser(String name, String password) {
     7       //添加日志/安全性检查
     8        //checksafe();
     9        //采用添加代理类的方法会如何?
    10        System.out.println("UserManagerImpl.addUser()123");
    11
    12    }

    13
    14    @Override
    15    public void delUser(String id) {
    16        //添加日志/安全性检查
    17        //checksafe();
    18           System.out.println("UserManagerImpl.delUser()");
    19    }

    20
    21    @Override
    22    public void modifyUser(int id, String name, String password) {
    23        //添加日志/安全性检查
    24        //checksafe();
    25           System.out.println("UserManagerImpl.modifyUser()");
    26
    27    }

    28//    private void checksafe(){
    29//        System.out.println("检查安全性的方法");
    30//    }
    31}

    32
    3.感觉应该叫切面的接口?
    1package com.zyl.proxy;
    2//切入点
    3public interface MySecurityManager {
    4     public void checkSafe();
    5}

    6
    4.实现
     1package com.zyl.proxy;
     2import org.aspectj.lang.annotation.Aspect;
     3import org.aspectj.lang.annotation.Before;
     4import org.aspectj.lang.annotation.Pointcut;
     5
     6
     7public class MySecurityManagerImpl implements MySecurityManager {
     8
     9
    10
    11
    12public void checkSafe() {
    13    System.out.println("checkSafe安全性检查");
    14
    15}

    16}

    17
    这里的切面的代码简化很多.只要写需要额外加入的方法即可.其他的声明放在配置文件中
    5.client
     1package com.zyl.ooxx;
     2
     3import org.springframework.beans.factory.BeanFactory;
     4import org.springframework.context.support.ClassPathXmlApplicationContext;
     5
     6import com.zyl.proxy.UserManager;
     7
     8
     9
    10public class client {
    11
    12    public static void main(String[] args) {
    13        //所有对象要从ioc中去取,所以之前这些对象要在xml中注册
    14        
    15        //通过配置文件初始化bean工厂
    16        BeanFactory factory =new ClassPathXmlApplicationContext("applicationContext.xml");
    17        //通过bean工厂得到UserManager
    18        UserManager usermanager=(UserManager)factory.getBean("userManagergb23122");
    19        
    20        usermanager.addUser("1""password");
    21        System.out.println("------------");
    22        usermanager.delUser("1");
    23        
    24        
    25    }

    26
    27}

    28
    其实认真看.这个和annotation方式的代码都一样啊.
    就只有4.MySecurityManagerImpl代码的简化.和6.配置文件的改变
    6.配置文件
     1<?xml version="1.0" encoding="UTF-8"?>
     2<beans xmlns="http://www.springframework.org/schema/beans" 
     3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     4    xmlns:context="http://www.springframework.org/schema/context" 
     5    xmlns:tx="http://www.springframework.org/schema/tx" 
     6    xmlns:aop="http://www.springframework.org/schema/aop" 
     7    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     8http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
     9http://www.springframework.org/schema/context 
    10http://www.springframework.org/schema/context/spring-context-2.5.xsd 
    11http://www.springframework.org/schema/aop 
    12http://www.springframework.org/schema/aop/spring-aop-2.5.xsd 
    13http://www.springframework.org/schema/tx 
    14http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> 
    15
    16
    17
    18<bean id="mySecurityManagerImp" class="com.zyl.proxy.MySecurityManagerImpl"/>
    19<bean id="userManagergb23122" class="com.zyl.proxy.UserManagerImpl"/>
    20
    21<aop:config>
    22   <!-- 配置切面 -->
    23   <aop:aspect id="securityAspect" ref="mySecurityManagerImp">
    24    <!-- 描述切入点 -->
    25    <aop:pointcut id="allAddMethod13" expression="execution(* add*(..))"/>  <!-- 切入点的什么,类似@Pointcut("execution(* add*(..))") 前一种方法中的这个写法 -->
    26    <!-- 描述advice -->
    27    <aop:before pointcut-ref="allAddMethod13" method="checkSafe"/><!-- 这个before标签说明是之前执行的. 注意id的对应.method就是新加入的方法的方法名了-->
    28   </aop:aspect>
    29</aop:config>
    30</beans>

    这个..变化就很大了
    具体看我的注释吧.
    参看前一种方式.就很好理解了
    小结:
    spring对aop的支持
     1.采用配置文件的方式
     2.将切面,切入点,通知等定义在配置文件中
     <aop:config>
       <!-- 配置切面 -->
       <aop:aspect id="securityAspect" ref="mySecurityManagerImp">
        <!-- 描述切入点 -->
        <aop:pointcut id="allAddMethod" expression="execution(* add*(..))"/>
        <!-- 描述advice -->
        <aop:before pointcut-ref="allAddMethod" method="checkSafe"/>
       </aop:aspect>
    </aop:config>
    --------------------
    p.s 我们可以得到切入点方法的信息(如addUser的方法名,传入参数的值)之前动态代理当时是怎么做的呢?
    代码如下:
     1public Object invoke(Object proxy, Method method, Object[] args)//args是传递过来的参数,比如name为张三
     2            throws Throwable 
     3        //调用任何方法前都会前调用invoke方法,所以我们在invoke方法前放置需要调用的代码 如安全性检查/log日志等等添加的方法
     4        //这里还可以加入一些逻辑判断,是否加入安全性检查
     5        checksafe();
     6         System.out.println("方法名是"+method.getName());
     7         for(int i=0;i<args.length;i++){
     8             System.out.println("哈哈"+args[i]);
     9         }

    10         //临时添加方法调用结束
    11         //以下调用一般的方法
    12        Object result=null;
    13        
    14        try{
    15            method.invoke(targetObj,args); //真正的调用对象的实现的方法(非添加的那些方法)
    16        }
    catch(Exception e){
    17            e.printStackTrace();
    18        }

    19        return result; //invoke方法需要返回一个对象.所以前面定义了一个Object result=null; 这里返回result
    20    }
    配置文件的方式:我们可以通过方法名来判断是否添加切面的内容.可是如何取得切入点方法的方法名,传入参数这些值呢?(比如addUser("男人都是","帅哥")可以取得方法名:addUser,男人都是,帅哥等参数)

      做法: 在通知中加入一个JoinPoint参数(大小写敏感),这个参数spring会自动传入,我们从JoinPoint中可以取得目标对象的相关信息,如参数,方法名等.
    将切面实现类修改即可:
     1package com.zyl.proxy;
     2
     3import org.aspectj.lang.JoinPoint;
     4
     5
     6
     7public class MySecurityManagerImpl  {
     8
     9
    10
    11
    12public void checkSafe(JoinPoint joinpoint) {
    13    Object[] args=joinpoint.getArgs();//得到参数
    14    for(int i=0;i<args.length;i++){
    15        System.out.println("参数是:"+args[i]);
    16    }

    17    System.out.println("方法名是:"+joinpoint.getSignature().getName());
    18    System.out.println("checkSafe安全性检查");
    19
    20}

    21}
    JointPoint自然会取得相应的信息.
    题外话:
    1.切面默认的情况下不需要接口(MySecurityManager接口其实可以不必存在);
    2.对于目标对象(UserManagerImpl类),默认情况下必须实现接口(jdk动态代理需要接口).
      如果不是用接口,我们要使用CGLIB库的支持才可以.
  • 相关阅读:
    使用TransactionScope实现事务
    CYQ.Data 框架系列
    MVP
    DYCOM用于开发网络应用程序的通信部分功能的快速开发
    架构师要了解
    Entity Framework资源
    Sina Blogs
    关于TransactionScope出错:“与基础事务管理器的通信失败”的解决方法总结
    在西方的程序员眼里,东方的程序员是什么样的?
    net2.0事务学习
  • 原文地址:https://www.cnblogs.com/redcoatjk/p/3562422.html
Copyright © 2020-2023  润新知