SpringAop的三种配置方法:基于ProxyFactoryBean、基于AspectJ的xml,基于AspectJ的注解
面向切面编程,是面向对象编程的一中拓展,将各个对象中的同级共性代码块提取出来进行方法封装。解耦,使得代码更加的简洁高效;其底层应用的原理是动态代理。可以增强方法,书写日志。
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("异常通知生效"); } }
- Spring4深入理解IOC&DI04----Bean配置方式(全类名,工厂方法,FactoryBean),配置形式(基于XML和注解),泛型依赖注入
- Spring 配置bean, 注解方式配置 xml方式要生产set方法方便属性注入,注解方式不需要,利用反射机制注入
- xml文件中bean的命名方式,使用注解和xml文件声明bean的对象的方法,实例化bean对象的三种方法
- Spring框架学习-深入理解AOP02----AOP简介,AspectJ,AOP基于注解和XML配置(5种通知,切面优先级)
- 使用TransactionProxyFactoryBean及abstract属性来简化配置 【声明式事务配置方法】
- Spring学习----------Bean配置的三种方式(XML、注解、Java类)介绍与对比
- Spring4深入理解AOP02----AOP简介,AspectJ,AOP基于注解和XML配置(5种通知,切面优先级)
- 实例化Bean的方法(基于xml配置)-http://blog.csdn.net/shymi1991/article/details/48153293
- Spring基础入门二:基于XML及注解配置完成Spring对Bean的注入
- 【Java.Spring.Core】【IoC】基于注解的Bean装配(非XML配置)
- Spring学习(二十二) Bean配置的三种方式(XML、注解、Java类)介绍与对比
- Spring-基于注解的配置[03Bean作用范围和生命周期方法]
- spring事务配置方法(TransactionProxyFactoryBean)
- 基于XML配置以及基于注解开发AspectJ实现AOP
- 先码后看 spring配置bean的几种方式:xml直接配置、静态工厂、实例工厂、factory bean、注解 侵立删
- spring 实例化定义在xml配置文件中的bean的三种方法?
- 基于@AspectJ注解配置切面与基于XML配置切面
- Spring配置bean的方法(工厂方法和Factorybean)
- Spring中TransactionProxyFactoryBean干啥的?为什么要配置这个东西?
- 基于XML配置方式实现对action的所有方法进行输入校验