关于Spring核心原理Aop的几种实现方式

我用的是spring4.3.11的jar包

1.配置文件的实现方式

代码写在aop包上

主业务接口,IMainBiz

package aop;

public interface IMainBiz {
	public void doMainBiz();
}

主业务实现类,MainBiz

package aop;

public class MainBiz  implements IMainBiz{

	public void doMainBiz()
	{
		System.out.println(1/0);
		System.out.println("核心业务");
	}
}
切面业务,SubBiz

package aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class SubBiz {

	public void doSubBiz(JoinPoint joinPoint)
	{
		//目标对象类信息
		System.out.println(joinPoint.getTarget().getClass().getSimpleName());
		System.out.println(joinPoint.getArgs());
		//切入点,主业务方法
		System.out.println(joinPoint.getSignature());
		System.out.println("切面业务");
		try {
			((ProceedingJoinPoint) joinPoint).proceed();
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("横切业务2");
	}
	public void doSubBiz2(Exception ex)
	{
		if(ex instanceof ArithmeticException)
		{
			System.out.println("数字异常");
		}
		else
		{
			System.out.println("未知异常");
		}
	}
}
测试类Main

package aop;

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

public class Main {
	public static void main(String[] args) {
		ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
		//cglib产生的代理对象,继承了mainbiz,经行子类扩展的功能
		//一定要接口接受
		IMainBiz mainBiz= (IMainBiz) applicationContext.getBean("mainbiz");
		mainBiz.doMainBiz();
	}
}
配置文件:applicationContext.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<!--目标对象 -->
	<bean id="mainbiz" class="aop.MainBiz"></bean>
	<!--切面 -->
	<bean id="subbiz" class="aop.SubBiz"></bean>
	<aop:config>
		<!--切入点 -->
		<aop:pointcut expression="execution(public void aop.MainBiz.doMainBiz())"
			id="pointcut" />
			<!--引入切面 -->
		<aop:aspect ref="subbiz">
		<!--切入策略 -->
			<!-- <aop:around method="doSubBiz" pointcut-ref="pointcut" /> -->
			<aop:after-throwing method="doSubBiz2" pointcut-ref="pointcut" throwing="ex"/>
		</aop:aspect>
	</aop:config>
</beans>

2. 实现通知接口并配合配置文件的方式

代码在advisor包上

主业务接口

package advisor;

public interface IMainBiz {
	public void doMainBiz();
}
主业务实现类

package advisor;

public class MainBiz  implements IMainBiz{

	public void doMainBiz()
	{
		System.out.println("核心业务");
	}
}
切面业务类,实现了接口

使用了advisor配置增强处理,

MethodBeforAdvice前置通知

AfterReturningAdvice后置通知,这个后置通知可以接受返回值,但是别的那几种方法是不能接收返回值

MethodInterceptor环绕通知

ThrowsAdvice异常通知,较为特殊,没有接口方法所以要手动在实现类中加入

public void afterThrowing(Method method,Object[] args,Object target,Exception ex){}

package advisor;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.aop.MethodBeforeAdvice;
//使用了Advisor配置增强处理
public class SubBiz implements MethodBeforeAdvice{
	
	

	@Override
	public void before(Method method, Object[] args, Object obj) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("切面方法");
	
	}
	
}
测试类Main

package advisor;

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

public class Main {
	public static void main(String[] args) {
		ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext2.xml");
		IMainBiz iMainBiz = (IMainBiz) applicationContext.getBean("mainbiz");
		iMainBiz.doMainBiz();
	}
}

配置文件applicationContext2.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">


	<bean id="mainbiz" class="adcisor.MainBiz"></bean>

	<bean id="subbiz" class="adcisor.SubBiz"></bean>

	<!--Aop配置  -->
	<aop:config>
		<aop:pointcut expression="execution(public void advisor.MainBiz.doMainBiz())" id="pointcut" />
		<!--切入策略  -->
		<aop:advisor advice-ref="subbiz" pointcut-ref="pointcut" />
	</aop:config>
</beans>

3.注解方式(个人觉得最简单的)

主业务接口ArithmeticCalculator

package test1;

public interface ArithmeticCalculator {
	int add(int a,int b);
	int sub(int a,int b);
	int multiply(int a,int b);
	int divide(int a,int b);
}
主业务实现类

package test1;

import org.springframework.stereotype.Component;
@Component("arithmeticCalculator")
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {

	@Override
	public int add(int a, int b) {
		int result = a + b;
		return result;
	}

	@Override
	public int sub(int a, int b) {
		int result = a - b;
		return result;
	}

	@Override
	public int multiply(int a, int b) {
		int result = a * b;
		return result;
	}

	@Override
	public int divide(int a, int b) {
		int result = a / b;
		return result;
	}

}
切面业务类

package test1;

import java.util.Arrays;
import java.util.List;

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.springframework.stereotype.Component;
//可以使用@order()来设置优先级,数字越小,优先级越高
@Aspect
@Component
public class LogginAspect {

	@Before("execution(public int test1.ArithmeticCalculatorImpl.*(int , int))")
	public void beforMethod(JoinPoint joinPoint)
	{
		String name = joinPoint.getSignature().getName();
		Object[] args = joinPoint.getArgs();
		List<Object> list = Arrays.asList(args);
		System.out.println("前置通知:"+name+" args "+list);
	}
	@After("execution(public int test1.ArithmeticCalculatorImpl.*(int , int))")
	public void afterMethod(JoinPoint joinPoint)
	{
		String name = joinPoint.getSignature().getName();
		Object[] args = joinPoint.getArgs();
		List<Object> list = Arrays.asList(args);
		System.out.println("后置通知:"+name+" args "+list);
	}
	@AfterReturning(value="execution(public int test1.ArithmeticCalculatorImpl.*(int , int))",
			returning="result")
	public void returnMethod(JoinPoint joinPoint,Object result)
	{
		
		String name = joinPoint.getSignature().getName();
		Object[] args = joinPoint.getArgs();
		List<Object> list = Arrays.asList(args);
		System.out.println("返回通知:"+name+" args "+list+" result "+result);
	}
	@AfterThrowing(value="execution(public int test1.ArithmeticCalculatorImpl.*(int , int))",
			throwing="ex")
	public void throwMethod(JoinPoint joinPoint,Exception ex)
	{
		
		String name = joinPoint.getSignature().getName();
		Object[] args = joinPoint.getArgs();
		List<Object> list = Arrays.asList(args);
		System.out.println("异常通知:"+name+" args "+list+" result "+ex);
	}
	@Around("execution(public int test1.ArithmeticCalculatorImpl.*(int , int))")
	public Object around(ProceedingJoinPoint pjd)
	{
		String methodname=pjd.getSignature().getName();
		Object proceed =null;
		//执行目标方法
		try {
			//前置通知
			System.out.println("the method :"+methodname+"  begins with" +Arrays.asList(pjd.getArgs()));
			proceed=pjd.proceed();
			//返回通知
			System.out.println("the method return  with "+ proceed);
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			System.out.println("the method pccurs exception "+e);
		}
		//后置通知
		System.out.println("the method end ");
		return proceed;
	}

 测试类Main 

package test1;

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

import com.sun.media.sound.AiffFileReader;

public class Main {
	public static void main(String[] args) {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext3.xml");
		ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) applicationContext
				.getBean("arithmeticCalculator");
		arithmeticCalculator.divide(3, 1);
//		System.out.println(add);
	}
}
配置文件applicationContext3.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
	<!--开启扫描包  -->
	<context:component-scan base-package="test1" />
	<!-- 开启aop注解驱动 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
在切面类加入支持的注解:
@before
@after 
@afterThrowing
@afterReturning
@aroud
@aspect
@pointcut
4. 通过实现接口方式

主业务接口IMainBiz

package aop2;

public interface IMainBiz {
	public void doMainBiz();
}

主业务实现类MainBiz

package aop2;

public class MainBiz  implements IMainBiz{

	public void doMainBiz()
	{
		System.out.println("核心业务");
	}
}
切面类SubBiz

package aop2;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.aop.MethodBeforeAdvice;

public class SubBiz implements MethodBeforeAdvice {

	public void doSubBiz() {
		System.out.println("切面方法");
	}

	@Override
	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
		doSubBiz();
	}

}
测试类Main

package aop2;

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

public class Main {

	public static void main(String[] args) {
		ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext4.xml");
			//这里getBean得到的不算主业务的id,而是ProxyFactoryBean的id
		IMainBiz  imMainBiz= (IMainBiz) applicationContext.getBean("myproxy");
		imMainBiz.doMainBiz();
	}
}

配置文件applicationContext4.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">


	<!-- 目标类-->
	<bean id="mainbiz" class="aop2.MainBiz"></bean>
	<!--切面类:实现通知接口-->
	<bean id="subbiz" class="aop2.SubBiz"></bean>
	
	<!-- 使用spring提供工厂类ProxyFactoryBean -->
	<bean id="myproxy"  class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="proxyInterfaces">
			<list>
				<value>aop2.IMainBiz</value>
			</list>
		</property>
		<!-- 目标类信息 -->
		<property name="targetName" value="mainbiz"></property>
		<!-- 切面类信息 -->	
		<property name="interceptorNames">
			<list>
				<value>subbiz</value>
			</list>
		</property>
	</bean>
</beans>
创建ProxyFactoryBean代理对象

<bean id="myproxy"  class="org.springframework.aop.framework.ProxyFactoryBean">
					//指定的目标类实现的接口
					<property name="proxyInterfaces">
						<list>
							<value>接口的完全限定名</value>
						</list>
					</property>
					<!-- 目标类信息 -->
					<property name="targetName" value="目标类ID"></property>
					<!-- 切面类信息 -->	
					<property name="interceptorNames">
						<list>
							<value>切面类的ID</value>
						</list>
					</property>
				</bean>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值