Spring——第三章 Spring与AOP(一)

       AOP是面向对象编程的一种补充,面向对象编程是从静态角度考虑程序的结构,而面向切面编程是从动态角度考虑程序的运行过程。

 

3.2.2 AOP编程术语

(1)切面(Aspect)

泛指交叉级业务逻辑。常用的切面有通知advice与顾问advisor,实际是对主业务逻辑的一种增强。

(2)织入(Weaving)

织入就是将切面代码插入到目标对象的过程中。

(3)连接点(JoinPoint)

可以被切面织入的方法。通常业务接口的方法均可被织入。

(4)切入点(Pointcut)

被织入的连接点叫做切入点。被final修饰的方法不能看作连接点,因为其不能被修改,不能被增强。

(5)目标对象(target)

要被增强的对象,即包含主业务逻辑的类的对象。

以下都是切面的一种:

(6)通知(Advice)

是切面的一种形式,可以完成简单的织入功能。通知定义了增强代码切入到目标代码的时间点,阿是目标方法执行之前执行还是执行之后执行。通知类型不同,切入时间不同。

切入点定义切入的位置,通知定义切入的时间。

(7)顾问(Advisor)

是将通知包装为更复杂切面的装配器。可以指定切入点。

 

3.3 通知Advice

 前置通知

package com.bjpowernode.aop01;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

// 前置通知
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {

	// 当前方法在目标方法执行之前执行
	// method:目标方法
	// args:目标方法的参数列表
	// target:目标对象
	@Override
	public void before(Method method, Object[] args, Object target)
			throws Throwable {
		// 对于目标方法的增强代码就应该写在这里
		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"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 注册目标对象 -->
    <bean id="someService" class="com.bjpowernode.aop01.SomeServiceImpl"/>
    
    <!-- 注册切面:通知 -->
    <bean id="myAdvice" class="com.bjpowernode.aop01.MyMethodBeforeAdvice"/>
    
    <!-- 生成代理对象 -->
    <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    	<!-- <property name="targetName" value="someService"/> -->
    	<!-- 指定目标对象 -->
    	<property name="target" ref="someService"/>
    	
    	<!-- 指定切面 -->
    	<property name="interceptorNames" value="myAdvice"/>
    </bean>

</beans>

执行前置通知方法
执行doFirst()方法
====================
执行前置通知方法
执行doSecond()方法

后置通知

package com.bjpowernode.aop02;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
//后置通知:可以获取到目标方法的返回结果,但无法改变目标方法的结果
public class MyAfterReturningAdvice implements AfterReturningAdvice {

	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("执行后置通知方法 returnValue= "+returnValue);
		if(returnValue!=null){
			returnValue = ((String)returnValue).toUpperCase();
			System.out.println("修改过的值:" + returnValue);
		}
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- 注册目标对象-->
	<bean id="myService" class="com.bjpowernode.aop02.SomeServiceImpl"/>
	
	<!--注册切片:advice -->
	<bean id="myAdvice" class="com.bjpowernode.aop02.MyAfterReturningAdvice"/>
	
	<!--生成proxy-->
	<bean id="myProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="target" ref="myService"/>
		<property name="interceptorNames" value="myAdvice"/>
	</bean>

</beans>

执行doFirst()方法
执行后置通知方法 returnValue= null
====================
执行doSecond()方法
执行后置通知方法 returnValue= abcde
修改过的值:ABCDE

环绕通知

package com.bjpowernode.aop03;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
//环绕通知:可以返回目标方法的返回结果
public class MyMethodInterceptor implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		System.out.println("执行环绕通知:目标方法执行之前");
		Object result = invocation.proceed();
		System.out.println("执行环绕通知:目标方法执行之后");
		if (result!=null) {
			result = ((String) result).toUpperCase();
		}
		return result;
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- 注册目标对象-->
	<bean id="myService" class="com.bjpowernode.aop03.SomeServiceImpl"/>
	
	<!--注册切片:advice -->
	<bean id="myAdvice" class="com.bjpowernode.aop03.MyMethodInterceptor"/>
	
	<!--生成proxy-->
	<bean id="myProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="target" ref="myService"/>
		<property name="interceptorNames" value="myAdvice"/>
	</bean>

</beans>

执行环绕通知:目标方法执行之前
执行doFirst()方法
执行环绕通知:目标方法执行之后
====================
执行环绕通知:目标方法执行之前
执行doSecond()方法
执行环绕通知:目标方法执行之后
ABCDE

异常通知

(1)

package com.bjpowernode.aop04;

import org.springframework.aop.ThrowsAdvice;
//异常通知
public class MyThrowAdvice implements ThrowsAdvice {
	//当目标方法抛出与指定类型的异常具有is-a关系的异常时,执行当前方法
	public void afterThrowing(Exception ex){
		System.out.println("执行异常通知方法");
	}
}
	public void doFirst() {
		System.out.println("执行doFirst()方法"+3/0);
	}

(2)

异常类:

package com.bjpowernode.aop05;
//异常分两种:
//1)运行时异常,不进行处理,也可以通过编译。
//      若一个类继承自RunTimeException,则该异常是运行时异常
//2)编译时异常,受查异常 checked Exception,不进行处理将无法通过编译
//     若一个类继承自Exception,则该异常就是受查异常
public class UserException extends Exception{

	public UserException() {
		super();
		// TODO Auto-generated constructor stub
	}

	public UserException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}
	
	
	
}
package com.bjpowernode.aop05;

public class UsernameException extends UserException {

	public UsernameException() {
		super();
		// TODO Auto-generated constructor stub
	}

	public UsernameException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}
	
}

package com.bjpowernode.aop05;

public class PasswordException extends UserException {

	public PasswordException() {
		super();
		// TODO Auto-generated constructor stub
	}

	public PasswordException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}
	
}



定义接口 抛出异常:

package com.bjpowernode.aop05;

public interface ISomeService {
	//目标方法
	boolean login(String username,String password) throws UserException;
}

实现接口:(实现类抛出相应的异常)

package com.bjpowernode.aop05;

public class SomeServiceImpl implements ISomeService{

	@Override
	public boolean login(String username, String password) throws UserException {
		if(!"root".equals(username)){
			throw new UsernameException("用户名输错啦");
		}
		if(!"123456".equals(password)){
			throw new PasswordException("密码输错啦");
		}
		//double a = 3/0;
		return true;
	}

}

 异常通知切片:(实现类抛出异常时会自动触发切片类afterThrowing方法)

package com.bjpowernode.aop05;

import org.springframework.aop.ThrowsAdvice;
//异常通知
public class MyThrowAdvice implements ThrowsAdvice {
	//当目标方法抛出与指定类型的异常具有is-a关系的异常时,执行当前方法
	public void afterThrowing(UsernameException ex){
		System.out.println("发生用户名异常 ex = "+ex.getMessage());
	}
	public void afterThrowing(PasswordException ex){
		System.out.println("发生密码异常 ex = "+ex.getMessage());
	}
	public void afterThrowing(Exception ex){
		System.out.println("发生其他异常 ex = "+ex.getMessage());
	}
}

 MyTest:

package com.bjpowernode.aop05;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
	@Test
	public void test01() throws UserException{
		String resource = "com/bjpowernode/aop05/applicationContext.xml";
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(resource);
		ISomeService service = (ISomeService) applicationContext.getBean("myProxy");
		service.login("root", "123456");
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值