哪建网站好,购买域名网,258网站建设,做网站最快多久AOP基础不了解可以阅读#xff1a;【Spring】AOP原来如此-CSDN博客
AspectJ是一个居于JAVA开发的AOP框架
基于XML的声明式AspectJ 基于XML的声明式AspectJ是通过XML文件来定义切面#xff0c;切入点及通知#xff0c;所有的切面、切入点和通知必须定义在内#xff0c;
元…AOP基础不了解可以阅读【Spring】AOP原来如此-CSDN博客
AspectJ是一个居于JAVA开发的AOP框架
基于XML的声明式AspectJ 基于XML的声明式AspectJ是通过XML文件来定义切面切入点及通知所有的切面、切入点和通知必须定义在内
元素及其子元素如下图所示 上图中Spring配置文件中元素下包含多个元素一个元素又包含属性和子元素它的子元素在配置时必须按照此顺序来定义在元素下同样包含了属性和多个子元素通过使用元素及其子元素可以在xml文件中配置切面、切入点和通知 1、配置切面 配置文件中用的是元素将一个定义好的SpringBean转换为切面Bean,所以要先定义好一个Bean,完成后ref引用即可 常用属性id和ref
package com.aqiuo.aspectj.xml;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
//切面类
public class MyAspect {//前置通知public void myBefore(JoinPoint joinPoint) {System.out.println(前置通知模拟执行权限检查);System.out.println(前置类是joinPoint.getClass());System.out.println(被植入增强处理的目标方法是joinPoint.getSignature().getName());}//后置通知public void myAfterReturning(JoinPoint joinPoint) {System.out.println(后置通知,模拟日志记录...);System.out.println(被置入增强处理的目标方法为joinPoint.getSignature().getName());}/*** 环绕通知* 返回值必须是Object* 必须接受一个参数参数类型必须是ProceedingJoinPoint* 方法必须抛异常*/public Object myAround(ProceedingJoinPoint joinPoint)throws Throwable {System.out.println(环绕开始执行方法前开启事务...);Object objectjoinPoint.proceed();System.out.println(环绕结束执行方法后关闭事务...);return object;}/*** 异常通知*/public void myAfterThrowing(JoinPoint joinPoint,Throwable e) {System.out.println(异常通知出错了e.getMessage());}/*** 最终通知*/public void myAfter(JoinPoint joinPoint) {System.out.println(最终通知。模拟方法结束后释放资源...);}
}
2、配置切入点 在Spring的配置文件中切入点是通过元素来定义的。当它作为的子元素定义时它是全局切入点可以被多个切面共享。当它作为元素的子元素时表示切入点只对当前切面有效 常用属性id和expression值如下 execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throw-pattern?)
例子execution(public String com.aqiuo.jdk.*.*(..))
表达式解释
modifier匹配修饰符public, private 等省略时匹配任意修饰符ret-type匹配返回类型使用 * 匹配任意类型declaring-type匹配目标类省略时匹配任意类型.. 匹配包及其子包的所有类name-pattern匹配方法名称使用 * 表示通配符() 匹配没有参数的方法(..) 匹配有任意数量参数的方法(,String) 匹配有两个参数的方法并且第一个为任意类型第二个为 String 类型throws-pattern匹配抛出异常类型省略时匹配任意类型
3、配置通知
通知常用的属性及其描述 pointcut 该属性用于指定一个切入点Spring将在匹配该表达式的连接点时织入该通知 pointcut-ref 该属性指定一个已经存在的切入点名称如配置代码中的myPointCut通常pointcut与pointcut-ref二选一 method 该属性指定一个方法名指定将切面bean中的该方法转换为增强处理 throwing 该属性只对元素有效用于指定一个形参名异常通知方法可以通过该形参访问目标方法所输出的异常 returning 该属性只对元素有效用于指定一个形参名后置通知方法可以通过该形参访问目标方法的返回值
示例 //xml文件?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.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 idmyAspect classcom.aqiuo.demo.MyAspect/beanaop:configaop:aspect idmyAspect refmyAspectaop:pointcut idpoint1 expressionexecution(public * com.aqiuo.service.impl.*.*(..))/aop:pointcut!--前置方法第一个执行--aop:before methodbefore pointcut-refpoint1/aop:before!--异常方法第三个执行--aop:after-throwing methodafter_throwing pointcut-refpoint1/aop:after-throwing!--后置方法第三个执行--aop:after-returning methodafter_returning pointcut-refpoint1/aop:after-returning!--最终方法第二个执行--aop:after methodafter pointcut-refpoint1/aop:after!--环绕方法--/aop:aspect/aop:config/beans//测试注意标签的摆放位置会导致执行的顺序出错要按一定的顺序排放 基于注解的声明式AspectJ
与基于代理类的AOP实现相比XML的声明式AspectJ要便捷很多但也存在Spring文件中配置大量代码信息为了解决这个问题AspectJ框架为AOP的实现提供了一套注解用来取代Spring配置文件中为实现AOP功能所配置的 臃肿代码
AspectJ的注解及其描述 Aspect 用来定义一个切面类 Pointcut 用来定义切入点表达式使用时还需要定义一个包含名字和任意参数的方法签名来表示切入点名称实际上这个方法签名就是一个返回值为void且方法体为空的普通方法 Before 用于定义前置通知 相当于BeforeAdvice在使用时通常需要指定一个value属性值该属性值用于指定一个切入点表达式可以是已经有的切入点也可以是切入点表达式 在目标方法执行之前执行执行的通知。无论何时都第一个执行 AfterReturning 用于定义后置通知相当于AfterReturningAdvice.在使用时可以指定 pointcut/value和returning属性其中pointcut/value两个属性的作用一样都是作用于指定切入点表达式returning属性值用于表示Advice方法中可以定义与此同名的形参。该形参用于访问目标方法值的返回值 在目标方法执行之后执行的通知。正常执行时第三个执行 Around 用于定义环绕通知相当于MethodInterceptor。在使用时需要指定一个value属性该属性用于指定该通知被植入的切入点 AfterThrowing 用于定义异常通知处理程序中未处理的异常相当于ThrowAdvice.在使用时可以指定pointcut/value和throw属性。pointcut/value用于指定切入点表达式throwing属性值用于指定一个形参名表示Advice方法中可定义与此同名的形参该形参可用于访问目标方法抛出的异常 在目标方法抛出异常时执行的通知。出现异常时第三个执行 After 最终通知不管是否异常都会执行 是在目标方法执行之后执行的通知。无论何时都第二个执行 DeclareParents 无需了解 配置切面
这个切面要加上Aspect 标注为切面类 Component:加入spring容器 Aspect
Component
public class MyAspect01 {Pointcut(value execution(public * com.aqiuo.service.impl.*.*(..)))public void pointCut(){}Before(value pointCut())public void before(JoinPoint joinPoint){System.out.println(注解前置通知);}AfterReturning(value pointCut() )public void afterReturning(JoinPoint joinPoint){System.out.println(注解后置通知);}After(value pointCut())public void after(JoinPoint joinPoint){System.out.println(注解最终通知);}AfterThrowing(value pointCut(),throwing e)public void afterThrowing(JoinPoint joinPoint,Throwable e){System.out.println(注解异常处理通知);e.printStackTrace();}Around(value pointCut())public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println(环绕注解前置);Object res proceedingJoinPoint.proceed();System.out.println(环绕注解后置);return res;}}在配置文件中加扫描标签和AOP的驱动注解标签 context:component-scan base-packagecom.aqiuo.service.impl/context:component-scan aop:aspectj-autoproxy/aop:aspectj-autoproxy ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:contexthttp://www.springframework.org/schema/contextxmlns:txhttp://www.springframework.org/schema/txxmlns:aophttp://www.springframework.org/schema/aopxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdcontext:component-scan base-packagecom.aqiuo.service.impl/context:component-scanaop:aspectj-autoproxy/aop:aspectj-autoproxy/beans 注意 如果同一个连接点有多个通知需要执行那在同一个切面中目标方法之前的前置通知和环绕通知的执行顺序是未知的目标方法之后的后置通知和环绕通知的执行顺序也是未知的注解才加用spring的配置自动完成创建代理织入切面的工作。必须要有否则没有增强有一个proxy-target-class属性默认为false表示使用jdk动态代理织入增强当配为时表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false如果目标类没有声明接口则spring将自动使用CGLib动态代理。 纯注解开发
配置注解类 EnableAspectJAutoProxy()这个是替代aop:aspectj-autoproxy 放在配置类上 package com.aqiuo.config;import com.aqiuo.aspect.MyAspect01;
import com.aqiuo.demo.MyAspect;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;Configurable
ComponentScan(com)
EnableAspectJAutoProxy()
Import(DaoConfig.class)
public class SpringConfig {}由于我dao层要用到数据源所以额外写了一个DAO的配置类初学不用可以不写
package com.aqiuo.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;import javax.sql.DataSource;public class DaoConfig {Beanpublic DataSource getDataSource(){DruidDataSource druidDataSourcenew DruidDataSource();druidDataSource.setDriverClassName(com.mysql.jdbc.Driver);druidDataSource.setUrl(jdbc:mysql://localhost:3306/ssm?characterEncodingutf-8);druidDataSource.setUsername(root);druidDataSource.setPassword(3.14159265358);return druidDataSource;}Beanpublic JdbcTemplate getJdbcTemplate(DataSource ds){JdbcTemplate jdbcTemplatenew JdbcTemplate();jdbcTemplate.setDataSource(ds);return jdbcTemplate;}}编写配置类
package com.aqiuo.aspect;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;Aspect
Component
public class MyAspect01 {Pointcut(value execution(public * com.aqiuo.service.impl.*.*(..)))public void pointCut(){}Before(value pointCut())public void before(JoinPoint joinPoint){System.out.println(注解前置通知);}AfterReturning(value pointCut() )public void afterReturning(JoinPoint joinPoint){System.out.println(注解后置通知);}After(value pointCut())public void after(JoinPoint joinPoint){System.out.println(注解最终通知);}AfterThrowing(value pointCut(),throwing e)public void afterThrowing(JoinPoint joinPoint,Throwable e){System.out.println(注解异常处理通知);e.printStackTrace();}Around(value pointCut())public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println(环绕注解前置);Object res proceedingJoinPoint.proceed();System.out.println(环绕注解后置);return res;}}被增强的方法 Service
public class AccountServiceImpl implements AccountService {AutowiredAccountMapper accountMapper;public Boolean pay(Integer money, Integer produce, Integer customer) throws SQLException {accountMapper.addMoney(money, produce);System.out.println(AccountService执行啦...);accountMapper.subMoney(money, customer);return false;}} 测试类 Testpublic void run2() throws SQLException {ApplicationContext applicationContextnew AnnotationConfigApplicationContext(SpringConfig.class);AccountService accountService (AccountService) applicationContext.getBean(AccountService.class);accountService.pay(100,1,2);}总结 1.纯xml配置文件方式 写一个类再xml文件中配置bean和即可 2.配置加注解 写一个切面类加上注解Aspect Component Before等 再配置文件中写 注解驱动 3.纯注解方式 在配置类上添加EnableAspectJAutoProxy() 其他不变注意扫描一定要都扫描到