您的位置:首页 > 编程语言 > ASP

SpringAop的三种配置方法:基于ProxyFactoryBean、基于AspectJ的xml,基于AspectJ的注解

2020-07-19 14:57 796 查看

面向切面编程,是面向对象编程的一中拓展,将各个对象中的同级共性代码块提取出来进行方法封装。解耦,使得代码更加的简洁高效;其底层应用的原理是动态代理。可以增强方法,书写日志。

Springxml头部声明:

[code]<?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">

</beans>

 

     

 

 

简单来说,连接点,就是程序执行过程中的各个阶段点。切点就是我们需要处理的地方,一般是方法。

切面就是我们的增强方法和业务逻辑。

基于ProxyFactoryBean的代理实现:

在ProxyFactoryBean的配置中,最重要的是两个点:切点和切面。

首先我们先在java中把对应的切面类配置好:这个类必须实现MethodInterceptor接口。具体为什么可以看动态代理的两种实现JDK和Cglib。

[code]public class myaspect implements MethodInterceptor {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {

System.out.println("方法被调用");
methodInvocation.proceed();

return null;
}
}

因为我们是基于Spring实现的Aop,所以在Spring的控制反转下,所有的实体都由Spring的容器创建,所以我们应该将切面加入容器中:

[code] <bean id="myaspect" class="com.aaa.aop.myaspect"></bean>

然后将我们需要代理的类也放在容器中:

[code]<bean id="studentDao" class="com.aaa.Dao.StudentImpl"></bean>

之后就是要让代理的类和切面发生关系。

[code]<bean  class="org.springframework.aop.framework.ProxyFactoryBean" id="factoryBean"  >
<property name="target" ref="studentDao"></property>
<property name="interceptorNames" value="myaspect"></property>

<property   name="proxyTargetClass" value="true"></property>
</bean>

为什么会有jdk和CGLIB两种选择?
1.jdk 只能代理类实现的接口的类,而没有实现接口类必须使用CGLIB
2.从性能来说:
CGLIB:创建慢,执行块
JDK:创建快,执行慢(反射本身执行就比正常代码的慢

从底层原理上来说:jdk动态代理实现的是创建一个实现被代理类的代理对象。而Cglib实现的是创建一个继承被代理类的代理对象。

之后我们就可以测试了。JDK (如果是想测试Cglib的话,需要将StudentDao换成他的实现类即可)。

[code] public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("AAop.xml");
// Cglib测试:
// StudentImpl studentImpl=(StudentImpl) applicationContext.getBean("factoryBean");
StudentDao studentDao= (StudentDao) applicationContext.getBean("factoryBean");
studentDao.findStudent();

}

分割线----------------------------------------------------------------------------------------------------------------------------------------------------------

基于AspectJ的AOP实现

1、基于xml的AspectJ

  切点表达式:切点表达式用来配置我们想要拦截哪些方法。

         格式:

     

[code]切点表达式:
public  void  com.aaa.Dao.StudentImpl.findStudent() throw
权限     返回类型   类限定名              方法名    参数  异常
省略      *      com.aaa.Dao.*.*(..)
其中  * 代表全部,(。。) 代表参数不限。

配置xml:

[code]<?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.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 目标对象-->
<bean id="studentDao" class="com.aaa.Dao.StudentImpl"></bean>

<!--获取切面 -->
<bean class="com.aaa.aop.AspectJ.xml.MyAspect" id="myAspect"></bean>
<!--配置对应的关系  基于aspectj织入   -->
<aop:config>
<!--声明一个切点,用来切方法 -->
<aop:pointcut id="myPoint" expression="execution(* com.aaa.Dao.*.*(..))"/>
<!--声明一个切面 用来增强方法 -->
<aop:aspect id="aspect" ref="myAspect" >
<!-- method="myBefore"   指定通知的方法
pointcut-ref="myPoint"     通知绑定的切点
-->
<aop:before method="myBefore" pointcut-ref="myPoint"></aop:before>
<aop:before method="myBefore1" pointcut-ref="myPoint"></aop:before>
<aop:after method="myAfter" pointcut-ref="myPoint"  ></aop:after>
<aop:after-returning method="myAfterReturning" returning="result1" pointcut-ref="myPoint"></aop:after-returning>
<aop:around method="myAround" pointcut-ref="myPoint"></aop:around>
<aop:after-throwing method="myThrow" pointcut-ref="myPoint" throwing="throwable"></aop:after-throwing>
</aop:aspect>

</aop:config>

写切面:

[code]package com.aaa.aop.AspectJ.xml;

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

/*
* 切面:公共代码抽取放置的位置
* */
public class MyAspect  {
// 前置通知
/*
* joinPoint  是连接点,用来链接切点和切面的参数

* */
public void myBefore(JoinPoint joinPoint){
System.out.println("前置方法生效");

}
public void myBefore1(JoinPoint joinPoint){
System.out.println("前置方法2");
}
public void myAfter(JoinPoint joinPoint){
System.out.println("最终方法生效");

}
//后置通知,目标方法执行调用,可以获取返回值
public void myAfterReturning(JoinPoint joinPoint,Object result1){
System.out.println("后置方法生效");
System.out.println("执行的结果"+result1);
}
// 环绕通知 proceeding 开始;执行
public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("环绕通知开始--方法"+proceedingJoinPoint.getSignature().getName());
Object result= proceedingJoinPoint.proceed();
System.out.println("环绕通知的结果"+result);

System.out.println("环绕通知结束方法:"+proceedingJoinPoint.getSignature().getName());
return  result;
}

// 异常通知
public void myThrow(JoinPoint joinPoint,Throwable throwable){
System.out.println("异常通知");

}

}

基于AspectJ注解的方式进行配置AOP

xml中:

[code]    <!--开启全自动注解 -->
<context:component-scan base-package="com.aaa"></context:component-scan>

<!-- 开启aspect aop 注解   -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

切面类中:

[code]package com.aaa.aop.AspectJ.Annotation;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component // 将切面加到容器中去
@Aspect  // 声明当前类是一个切面
public class MyAspect {
/*
* 声明一个切点
* */
// public  void  com.aaa.Dao.StudentImpl.findStudent() throw
//  省略     *    com.aaa.Dao.*.*(..)                   省略

@Pointcut("execution( *    com.aaa.Dao.*.*(..) )")
public void myPoint(){

}
@Before("myPoint()")
public void myBefore(JoinPoint joinPoint){
System.out.println("前置通知");
}
@After("myPoint()")
public void myAfter(JoinPoint joinPoint){
System.out.println("注解最终通知执行");
}
@AfterReturning(value = "myPoint()",returning = "result")
public void myAfterRunning(JoinPoint joinPoint,Object result){
System.out.println("后置方法执行"+result);
}
@Around("myPoint()")
public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕方法执行");
Object o= proceedingJoinPoint.proceed();
System.out.println("执行结果为"+o);

System.out.println("环绕通知结束");
return o;
}

@AfterThrowing(value = "myPoint()",throwing = "throwable")
public void myThrow(JoinPoint joinPoint,Throwable throwable){
System.out.println("异常通知生效");
}

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐