通过手机银行app对spring中的aop的使用进行简单讲解以及配置步骤,返回值后置通知,环绕通知,异常通知,

注意,我们在执行业务的时候必须先执行isSecurity()方法,然后再执行业务中的那三个方法。然后执行log以及clearResource方法。要实现上述操作流程,可以创建一个BankServiceProxy类将其他几个模块进行合包(这里将其他几个类看为几个不同的模块),再创建一个Window类进行调用。看上图,除了第二行之外,其他几个称之为切面,切面中的方法称之为通知,Security、Clean、RiZhi都为切面。



2. 通知:切面中的方法为通知
a) 前置通知:在目标方法之前执行的方法
b) 后置通知:在目标方法之后执行的方法
c) 环绕通知
d) 异常通知
3. 连接点:目标方法
4. 织入:将目标方法、通知等连接起来的过程

代码如下:

package cn.java.java.aop2;

public class Window {

	public static void main(String[] args) {
		BankServiceProxy bsP=new BankServiceProxy();
		bsP.chaMoney();//调用查询的方法

	}

}
package cn.java.java.aop2;
/**
 * 代理类
 * @author 26326
 *
 */

public class BankServiceProxy {
	
    private BankServiceImpl bsi=new BankServiceImpl();
    private Security s=new Security();
    private RiZhi rz=new RiZhi();
    private Clean c=new Clean();
    public void chaMoney() {
    	s.isSecurity();
    	bsi.getMoney();
    	rz.log();
    	c.clearResource();
    	
    }
    public void moneyZhuan() {
    	s.isSecurity();
    	bsi.zhuanMoney();
    	rz.log();
    	c.clearResource();
    	
    }
    public void moneyInvest() {
    	s.isSecurity();
    	bsi.invest();
    	rz.log();
    	c.clearResource();
    	
    }
    
}
package cn.java.java.aop2;
/**
 * 清空数据
 * @author 26326
 *
 */

public class Clean {
	public void clearResource() {
		 System.out.println("RiZhi........clearResource()........数据已经清空");
		
	}

}

package cn.java.java.aop2;

/**
 * 日志
 * @author 26326
 *
 */

public class RiZhi {
	public void log() {
		 System.out.println("RiZhi........log()........记录日志");
		
	}
	
	

}
package cn.java.java.aop2;
/**
 * 环境监测
 * @author 26326
 *
 */

public class Security {
	public void isSecurity() {
		 System.out.println("Security........isSecurity()........");
		
	}
	

}
package cn.java.java.aop2;

public class BankServiceImpl {

	 /**
	  * 查询余额
	  */
	public void getMoney() {
		  System.out.println("BankServiceImpl........getMoney()........余额为500万");
		
	}
	/**
	 * 转账
	 */
	public void zhuanMoney() {
		
		 System.out.println("BankServiceImpl........zhuanMoney()........转账100万");
	}
	/**
	 * 投资理财
	 */
	
	public void invest() {
		 System.out.println("BankServiceImpl........invest()........投资成功");
		
	}
}

接下来,我们可以通过配置来实现。这里用的是自己创建的一个aop.xml的局部配置文件,然后还要在applicationContext中进行关联,

同时,项目中必须有如下的jar包:


还要进行如下的配置,注意在局部配置文件中也做如下的配置,这样在写<aop>标签时就会有提示。


将http://www.springframework.org/schema/aop/spring-aop-2.5.xsd放入key中,location是在本地中的


这个文件的位置,


这样就配置完毕。

然后在aop配置文件中对切面进行配置,如果以后不需要这个功能了,可以在配置文件直接删除对它的配置。

下面是相关代码:

这是aop.xml配置文件

<?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"
	   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-->
<bean id="security" class="cn.java.java.aop2.Security"></bean>

<!-- 配置核心业务bean-->
<bean id="bankServiceImpl" class="cn.java.java.aop2.BankServiceImpl"></bean>

<!-- 配置日志bean-->
<bean id="riZhi" class="cn.java.java.aop2.RiZhi"></bean>

<!-- 配置清空数据bean-->
<bean id="clean" class="cn.java.java.aop2.Clean"></bean>

<!-- 配置aop -->
<aop:config >
<!-- 首先配置切入点,id可随便写,cn.java.java.aop2.BankServiceImpl.*:表示BankServiceImpl类中的所有方法都是切入点 
   <aop:pointcut expression="cn.java.java.aop2.BankServiceImpl.*" id="aaa"/>,这个不常用
   下面的表示将cn.java.java.aop2.BankServiceImpl中的所有方法作为切入点,这个方法可能带参数也可能不带参数
   -->
   <aop:pointcut expression="execution (* cn.java.java.aop2.BankServiceImpl.* (..))" id="aaa"/>
   
   <!-- 然后配置切面 (切面中的方法称之为通知),注意:ref中的值和bean中的id值一致-->
   <aop:aspect ref="security">
     <!-- aop:before 代表前置通知,在执行这个类的方法的时候会先执行这个方法
             method  通知方法名,
             pointcut-ref 切入点id
      -->
        <aop:before method="isSecurity" pointcut-ref="aaa"/>     
    </aop:aspect>
    
    <!-- 配置日志切面,order数值越大越先执行 -->
    <aop:aspect ref="riZhi" order="2">
       <aop:after method="Log"  pointcut-ref="aaa"/>
    </aop:aspect>
    
    <!-- 配置清空数据切面 -->
    <aop:aspect ref="clean" order="1">
      <aop:after method="clearResource"  pointcut-ref="aaa"/>
    </aop:aspect>
</aop:config>

</beans>

<?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"
	   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">



           <import resource="cn/java/di/jvbu.xml"/>
          
</beans>
package cn.java.java.aop2;
/**
 * 环境监测
 * @author 26326
 *
 */

public class Security {
	public void isSecurity() {
		 System.out.println("Security........isSecurity()........");
		
	}
	

}
package cn.java.java.aop2;

/**
 * 日志
 * @author 26326
 *
 */

public class RiZhi {
	public void log() {
		 System.out.println("RiZhi........log()........记录日志");
		
	}
	
	

}
package cn.java.java.aop2;
/**
 * 清空数据
 * @author 26326
 *
 */

public class Clean {
	public void clearResource() {
		 System.out.println("RiZhi........clearResource()........数据已经清空");
		
	}

}

package cn.java.java.aop2;

public class BankServiceImpl {

	 /**
	  * 查询余额
	  */
	public void getMoney() {
		  System.out.println("BankServiceImpl........getMoney()........余额为500万");
		
	}
	/**
	 * 转账
	 */
	public void zhuanMoney() {
		
		 System.out.println("BankServiceImpl........zhuanMoney()........转账100万");
	}
	/**
	 * 投资理财
	 */
	
	public void invest() {
		 System.out.println("BankServiceImpl........invest()........投资成功");
		
	}
}

在window类中进行调用结果如下:




三 带返回值的后置通知

现在希望业务中的那三个功能都能返回结果,并且都能被后面的切面receive接收到,注意只接收有参数的,否则就不会调用receive方法。

receive类:

package cn.java.java.aop2;

/**
 * 用来接收目标方法返回值的切面
 * @author 26326
 *
 */
public class Receive {
	public void printMoney(Object m) {//这里为object类型,可以解决调用的方法中与这里接收的信息类型不匹配的问题
		 System.out.println("当前余额为:"+m);
		
	}
	

}

接下来是在aop中的配置:

<?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"
	   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-->
<bean id="security" class="cn.java.java.aop2.Security"></bean>

<!-- 配置核心业务bean-->
<bean id="bankServiceImpl" class="cn.java.java.aop2.BankServiceImpl"></bean>

<!-- 配置日志bean-->
<bean id="riZhi" class="cn.java.java.aop2.RiZhi"></bean>

<!-- 配置清空数据bean-->
<bean id="clean" class="cn.java.java.aop2.Clean"></bean>

<!-- 配置接收返回值的切面 -->
<bean id="receive" class="cn.java.java.aop2.Receive"></bean>


<!-- 配置aop -->
<aop:config >
<!-- 首先配置切入点,id可随便写,cn.java.java.aop2.BankServiceImpl.*:表示BankServiceImpl类中的所有方法都是切入点 
   <aop:pointcut expression="cn.java.java.aop2.BankServiceImpl.*" id="aaa"/>,这个不常用
   下面的表示将cn.java.java.aop2.BankServiceImpl中的所有方法作为切入点,这个方法可能带参数也可能不带参数
   -->
   <aop:pointcut expression="execution (* cn.java.java.aop2.BankServiceImpl.* (..))" id="aaa"/>
   
   <!-- 然后配置切面 (切面中的方法称之为通知),注意:ref中的值和bean中的id值一致-->
   <aop:aspect ref="security">
     <!-- aop:before 代表前置通知,在执行这个类的方法的时候会先执行这个方法
             method  通知方法名,
             pointcut-ref 切入点id
      -->
        <aop:before method="isSecurity" pointcut-ref="aaa"/>     
    </aop:aspect>
    
    
    <!-- 配置日志切面,order数值越大越先执行 -->
    <aop:aspect ref="riZhi" order="2">
       <aop:after method="Log"  pointcut-ref="aaa"/>
    </aop:aspect>
    
    
    <!-- 配置清空数据切面 -->
    <aop:aspect ref="clean" order="1">
      <aop:after method="clearResource"  pointcut-ref="aaa"/>
    </aop:aspect>
    
    
    <!-- 配置接收参数的切面 -->
    <aop:aspect ref="receive">
      <aop:after-returning method="printMoney" pointcut-ref="aaa" returning="m"/>
    </aop:aspect>
    
</aop:config>

</beans>
下图是结果:


四 环绕通知

只有满足条件的时候,后面的前置通知与后置通知才能去执行。


创建Auth类:

package cn.java.java.aop2;

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 验证用户名与密码是否正确的切面
 * @author 26326
 *
 */

public class Auth {
     
	private String username="admin";
	private String password="123";
	//ProceedingJoinPoint是spring框架传递来的
	public void isUserExist(ProceedingJoinPoint pp) throws Throwable{
		if("admin".equals(username)&&"123".equals(password)) {
			//放行
			pp.proceed();
			
		}else {
			//用户名或者密码错误
			System.out.println("登录错误");
		}
		
	}
	
}
<?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"
	   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-->
<bean id="security" class="cn.java.java.aop2.Security"></bean>

<!-- 配置核心业务bean-->
<bean id="bankServiceImpl" class="cn.java.java.aop2.BankServiceImpl"></bean>

<!-- 配置日志bean-->
<bean id="riZhi" class="cn.java.java.aop2.RiZhi"></bean>

<!-- 配置清空数据bean-->
<bean id="clean" class="cn.java.java.aop2.Clean"></bean>

<!-- 配置接收返回值的切面 -->
<bean id="receive" class="cn.java.java.aop2.Receive"></bean>

<!-- 配置验证用户姓名与密码的切面 -->
<bean id="auth" class="cn.java.java.aop2.Auth"></bean>

<!-- 配置aop -->
<aop:config >
<!-- 首先配置切入点,id可随便写,cn.java.java.aop2.BankServiceImpl.*:表示BankServiceImpl类中的所有方法都是切入点 
   <aop:pointcut expression="cn.java.java.aop2.BankServiceImpl.*" id="aaa"/>,这个不常用
   下面的表示将cn.java.java.aop2.BankServiceImpl中的所有方法作为切入点,这个方法可能带参数也可能不带参数
   -->
   <aop:pointcut expression="execution (* cn.java.java.aop2.BankServiceImpl.* (..))" id="aaa"/>
   
   
    <!-- 配置验证用户姓名与密码的环绕通知的切面 -->
    <aop:aspect ref="auth">
      <aop:around method="isUserExist" pointcut-ref="aaa" />
    </aop:aspect>
    
    
   
   <!-- 然后配置切面 (切面中的方法称之为通知),注意:ref中的值和bean中的id值一致-->
   <aop:aspect ref="security">
     <!-- aop:before 代表前置通知,在执行这个类的方法的时候会先执行这个方法
             method  通知方法名,
             pointcut-ref 切入点id
      -->
        <aop:before method="isSecurity" pointcut-ref="aaa"/>     
    </aop:aspect>
    
    
    <!-- 配置日志切面,order数值越大越先执行 -->
    <aop:aspect ref="riZhi" order="2">
       <aop:after method="Log"  pointcut-ref="aaa"/>
    </aop:aspect>
    
    
    <!-- 配置清空数据切面 -->
    <aop:aspect ref="clean" order="1">
      <aop:after method="clearResource"  pointcut-ref="aaa"/>
    </aop:aspect>
    
    
    <!-- 配置接收参数的切面 -->
    <aop:aspect ref="receive">
      <aop:after-returning method="printMoney" pointcut-ref="aaa" returning="m"/>
    </aop:aspect>
    
    
   
    
</aop:config>

</beans>




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值