Java网课基础笔记(15)19-07-28

1.AOP注解配置

package com.feng.zhujie;
//接口
public interface ICustomerService {
	//保存
	public void save();
	//查询
	public Integer find();
}
package com.feng.zhujie;
import org.springframework.stereotype.Service;
//实现类
@Service("customerService")
public class CustomerServiceImpl implements ICustomerService{
	@Override
	public void save() {
		// TODO Auto-generated method stub
		System.out.println("客户保存");
	}
	@Override
	public Integer find() {
		System.out.println("客户查找");
		return 88;
		// TODO Auto-generated method stub
	}
}
//没有接口的类
package com.feng.zhujie;
import org.springframework.stereotype.Service;
@Service("productService")
public class ProductService {
	public void save() {
		System.out.println("商品保存");
	}
	public Integer find() {
		System.out.println("商品查找");
		//测试抛出通知的时候设置异常
		//int i=1/0;
		return 99;
	}
}
//测试类
package com.feng.zhujie;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//Springjunit集成测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpringTest {
	//注入要测试bean
	@Autowired
	private ICustomerService customerService;
	@Autowired
	private ProductService productService;
	//测试
	@Test
	public void test() {
		//基于接口
		customerService.save();
		customerService.find();
		//基于类
		productService.save();
		productService.find();
	}

}
//切面类
package com.feng.zhujie;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
//advice通知增强类
//<bean id="myAspect" class="com.feng.zhujie.MyAspect"></bean>
@Component("MyAspect")
//<aop:aspect ref="myAspect">
@Aspect
public class MyAspect {
//注解前置通知两种方法
	// 第一种:可以直接将切入点的表达式或切入点名字写到@Before
	@Before("bean(*Service)")
	public void before1(JoinPoint joinPoint) {
		System.out.println("--111前置通知--");
	}
//第二种:可以使用自定义方法,使用@Pointcut定义切入点
	/**
	 * 切入点方法的语法要求:切点方法:private void 无参数、无方法体,方法名为切入点的名称
	 * 一个通知方法@Before可以使用多个切入点表达式,中间使用“||”符号分隔,用来表示多个切入点
	 */
	// <aop:point expression="bean(customerService)" id="myPointcut1"/>
	@Pointcut(value = "bean(customerService)")
	private void myPointcut1() {
	}
	// <aop:point expression="bean(customerService)" id="myPointcut2"/>
	@Pointcut(value = "bean(productService)")
	private void myPointcut2() {
	}
	// <aop:before method="before" pointcut-ref="myPointcut1"/>
	// <aop:before method="before" pointcut-ref="myPointcut2"/>
	@Before("myPointcut1()||myPointcut2()")
	public void before2(JoinPoint joinPoint) {
		System.out.println("--222前置通知--");
	}

	// 后置通知
	// target:拦截某一个类型的bean(唯一),表示只对CusotomerServiceImpl类中的方法做后置通知的查找
	@AfterReturning(value = "target(com.feng.zhujie.CustomerServiceImpl)", returning = "returnVal")
	public void afterReturning(JoinPoint joinPoint, Object returnVal) {
		System.out.println("--后置通知--");
	}

	// 环绕通知
	/**
	 * @Around("execution(* com.feng*.*(..))")
	 * 增强返回类型任意,所有的com.feng包中的类,类中所有的方法,参数任意 @Around("execution(*
	 * com.feng..*.*(..))")
	 * 增强返回类型任意,所有的com.feng包中的类,及其子包中的所有类,类中所有的方法,参数任意 @Around("execution(*
	 * com.feng..*.save(..))") 增强返回类型任意,所有的com.feng包中的类,及其子包中的所有类,类中以save结尾的方法,参数任意
	 */
	// 增强com.feng包中的ICustomerService类的子类型的所有方法,参数任意
	@Around("execution(* com.feng.zhujie.ICustomerService+.*(..))")
	public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
		System.out.println("--环绕通知-前--");
		Object object = proceedingJoinPoint.proceed();
		System.out.println("--环绕通知-后--");
		return object;
	}

	// 抛出通知
	// 切入点表达式:增强所有com包以及子包下面的所有类型的bean的所有方法
	@AfterThrowing(value = "within(com..*)", throwing = "ex")
	public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
		System.out.println("--抛出通知--" + "抛出的异常信息" + ex.getMessage());
	}

	// 最终通知
	// 拦截所有以ice结尾的bean
	@After("bean(*ice)")
	public void after(JoinPoint joinPoint) {
		System.out.println("--最终通知--");
	}

}
//applicationContext.xml
<!-- 扫描com.feng.zhujie包下的所有Java类 -->
	<context:component-scan
		base-package="com.feng.zhujie"></context:component-scan>
	<!-- 配置aop的aspectj的自动代理 自动扫描bean组件,含有@Aspect的bean,将其为aop管理,开启动态代理 -->
	<aop:aspectj-autoproxy ></aop:aspectj-autoproxy>

前置、后置、环绕、最终通知测试

异常通知测试

【扩展补充】:aop代理是使用的spring的内部代理机制,默认是如果有接口就优先对接口代理(jdk动态代理)

问题:如果目标对象有接口,能否只对实现类代理,而不对接口进行代理呢?可以的。

          1.在CustomerServiceImpl的子类中添加一个新的方法update(),而接口不要定义update()的方法

package com.feng.zhujie;
import org.springframework.stereotype.Service;
//实现类
@Service("customerService")
public class CustomerServiceImpl implements ICustomerService{
	@Override
	public void save() {
		// TODO Auto-generated method stub
		System.out.println("客户保存");
	}
	@Override
	public Integer find() {
		System.out.println("客户查找");
		return 88;
		// TODO Auto-generated method stub
	}
	//方法在接口没有
	public void update() {
		System.out.println("客户更新");
	}
}

          2.在测试类中调用子类的扩展方法

public void test() {
		//基于接口
		customerService.save();
		customerService.find();
		//基于类
		productService.save();
		productService.find();
		//执行customerService的update方法
        //扩展方法执行:customerServic是一个动态代理对象,原因,该对象是接口的子类型的对象
		((CustomerServiceImpl) customerService).update();
	}

直接测试发现异常

原因:代理的目标对象是接口,无法转换为子类

解决办法:可以使用类代理(cglib动态代理),只需要设置proxy-target-class=true;

在applicationContex.xml中修改如下配置

<!-- 配置aop的aspectj的自动代理 自动扫描bean组件,含有@Aspect的bean,将其为aop管理,开启动态代理 -->
	<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值