• SSH深度历险(十一) AOP原理及相关概念学习+xml配置实例(对照注解方式的优缺点)


    接上一篇

     SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP,本篇我们主要是来学习使用配置XML实现AOP


    本文採用强制的CGLB代理方式


    SecurityHandler这个通知类能够换成安全性检測、日志管理等等。


    <span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package com.bjpowernode.spring;
    
    import org.aspectj.lang.JoinPoint;
    
    
    public class SecurityHandler {
    	
    	private void checkSecurity(JoinPoint joinPoint) {
    		for (int i=0; i<joinPoint.getArgs().length; i++) {
    			System.out.println(joinPoint.getArgs()[i]);
    		}
    		
    		System.out.println(joinPoint.getSignature().getName());
    		
    		System.out.println("-------checkSecurity-------");
    	}		
    }
    </span></span></span>


    UserManager接口


    <span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package com.bjpowernode.spring;
    
    public interface UserManager {
    
    	public void addUser(String username, String password);
    	
    	public void delUser(int userId);
    	
    	public String findUserById(int userId);
    	
    	public void modifyUser(int userId, String username, String password);
    }
    </span></span></span>

    UserManagerImpl接口的实现
    <span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package com.bjpowernode.spring;
    
    public class UserManagerImpl implements UserManager {
    
    	public void addUser(String username, String password) {
    		//checkSecurity();
    		System.out.println("---------UserManagerImpl.add()--------");
    	}
    
    	public void delUser(int userId) {
    		//checkSecurity();
    		System.out.println("---------UserManagerImpl.delUser()--------");
    	}
    
    	public String findUserById(int userId) {
    		//checkSecurity();
    		System.out.println("---------UserManagerImpl.findUserById()--------");
    		return "张三";
    	}
    
    	public void modifyUser(int userId, String username, String password) {
    		//checkSecurity();
    		System.out.println("---------UserManagerImpl.modifyUser()--------");
    	}
    
    //	private void checkSecurity() {
    //		System.out.println("-------checkSecurity-------");
    //	}
    }
    </span></span></span>

    applicationContext.xml中进行配置( <!-- 强制使用CGLIB代理 -->  )


    <span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"><?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"
    	     xmlns:tx="http://www.springframework.org/schema/tx"
    	     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
        <!-- 强制使用CGLIB代理 -->  
        <!--      
    	<aop:aspectj-autoproxy proxy-target-class="true"/>
    	 -->
    	 
    	<bean id="userManager" class="com.bjpowernode.spring.UserManagerImpl"/>
    	<bean id="securityHandler" class="com.bjpowernode.spring.SecurityHandler"/>
    	
    	<aop:config>
    		<aop:aspect id="securityAspect" ref="securityHandler">
    			<!--
    			以add开头的方法 
    			<aop:pointcut id="addAddMethod" expression="execution(* add*(..))"/>
    			 -->
    			 <!-- 
    			 com.bjpowernode.spring包下全部的类全部的方法
    			<aop:pointcut id="addAddMethod" expression="execution(* com.bjpowernode.spring.*.*(..))"/>
    			 --> 
    			<aop:pointcut id="addAddMethod" expression="execution(* com.bjpowernode.spring.*.add*(..)) || execution(* com.bjpowernode.spring.*.del*(..))"/> 
    			<aop:before method="checkSecurity" pointcut-ref="addAddMethod"/>
    		</aop:aspect>
    	</aop:config>
    </beans>
    </span></span></span>

    Clientclient的调用


    <span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">package com.bjpowernode.spring;
    
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Client {
    
    	public static void main(String[] args) {
    		BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
    		
    		UserManagerImpl userManager = (UserManagerImpl)factory.getBean("userManager");
    		userManager.addUser("张三", "123");
    		
    	}
    
    }
    </span></span></span>

    终于效果




    AOP两种代理的差别

         Jdk基于接口实现:JDK动态代理对实现了接口的类进行代理。

    • CGLIB基于继承:CGLIB代理能够对类代理,主要对指定的类生成一个子类,由于是继承,所以目标类最好不要使用final声明。
    • 假设目标对象实现了接口,默认情况下採用JDK的动态代理实现AOP,也能够强制使用CGLB生成代理实现;
    • 假设目标对象没有实现接口,那么必须引入CGLB,spring会在JDK的动态代理和CGLB代理之间切换

           通常情况下,鼓舞使用jdk代理,由于业务一般都会抽象出一个接口。并且不用引入新的东西。假设是遗留的系统。曾经没有实现接口。那么仅仅能使用CGLIB。

            普通情况下优先採用JDK动态代理,尽管其效率似乎比不上CGLIB代理。可是其对象用完之后能够正常释放。可是CGLIB代理每代理一个对象,都会产生一个新类。而类一旦加载JVM,依照大部分JVM的机制,这些新类占用的内存不会释放。J2EE程序一般执行时间都非常长。内存上会有一些压力。


    XML和AspectJ注解方式配置优缺点对照


            用XML风格,则全部的切面、切点、通知等配置都写在一个或几个Spring配置文件中。这种优点是,从配置文件中,就能够非常清晰的看出系统中的有哪些切面,某个切面里使用那个的通知(advice)以及通知(advice)作用的切点。

    而在AspectJ风格中,在java程序中标识切面则显得凌乱、模糊。


    在什么情况下使用注解形式的AOP?

    或者说使用注解来实现AOP有哪些长处呢?
       
        1. XML风格的AOP只支持"singleton"切面实例模型,而採用AspectJ风格的AOP则
    没有这个限制。



        2.XML风格的AOP中是不支持命名连接点的声明,而採用AspectJ风格的AOP则没有这个限制。

    不太理解的看以下实例代码:
      在@AspectJ风格中我们能够编写例如以下的内容:



    <span style="font-size:18px;">    @Pointcut(execution(* get*()))  
                        public void propertyAccess() {}  
                          
                        @Pointcut(execution(org.xyz.Account+ *(..))  
                        public void operationReturningAnAccount() {}  
                          
                        @Pointcut(propertyAccess() && operationReturningAnAccount())  
                    public void accountPropertyAccess() {}  </span>

    在XML风格中,我们不能使用'&&'字符来连接命名连接点,例如以下:


    <span style="font-size:18px;">    <aop:pointcut id="propertyAccess"  
                        expression="execution(* get*())"/>  
                          
                        <aop:pointcut id="operationReturningAnAccount"  
                    expression="execution(org.xyz.Account+ *(..))"/>  
                    <!-- 错误的配置  -->  
                  <aop:pointcut id="accountPropertyAccess"  
                    expression="propertyAccess && operationReturningAnAccount"/>  </span>

    注意: XML风格AOP尽管不支命名连接点的声明,可是,能够使用例如以下形式处理,例如以下配置:


    <span style="font-size:18px;">    <aop:pointcut id="propertyAccess"  
                        expression="execution(* get*())"/>  
           <aop:pointcut id="operationReturningAnAccount"  
                    expression="execution(org.xyz.Account+ *(..))"/>  
            <aop:pointcut id="accountPropertyAccess"  
                    expression="execution(* get*()) and execution(org.xyz.Account+ *(..))"/>  </span>


    总结

           这两种方法都实现了AOP,提高了我们的程序代码复用率,非常好的体现了抽象带来的优点,两者相互补充,相互借鉴,我们依据实际情况适当的选取和决策,在系统开发环境下适合开发的流程才是最重要的,

         

  • 相关阅读:
    1
    iulg
    实验10
    作业5 指针应用
    作业4 函数应用
    实验9 指针
    实验 8 数组2
    实验7
    实验6 数组1
    实验5
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/6812803.html
Copyright © 2020-2023  润新知