Spring框架 spring-aop (spring框架的优点)
Spring框架 spring-aop (spring框架的优点)
1.Spring中的aop
Aop是面向切面的编程思想,在Spring框架中的Spring-aop.jar模块提供了aop的支持,但它并不是一个完整的AOP解决方案。
AspectJ是基于java语言的AOP框架,它定义了AOP的语法,使用专门的编译器生成符合JAVA编码规范的字节码。
2.增强类型(通知)
AOP的实现无论采用代理还是预编译式织入,都是为了增强目标代码的功能。
3.SpringAop
springAop使用动态代理的方式实现AOP,动态代理的实现可采用JDK动态代理或CGLIB的方式。JDK动态代理是基于接口,CGLIB不能代理final类。所以采用springAop方式时,要注意被代理的对象要么实现了某接口,也不能是final类。
3.1.实现流程
1.编写增强类
/**
* MethodBeforeAdvice:前置通知接口
* MethodInterceptor:环绕通知接口
* AfterReturingAdvice:后置通知接口
*/
publicclass SpringAopAspect implements
//AfterReturningAdvice, MethodBeforeAdvice,
MethodInterceptor
{
private Logger logger =LoggerFactory.getLogger(SpringAopAspect.class);
//环绕增强方法
@Override
public Object invoke(MethodInvocationmethodInvocation) throws Throwable {
Object ret=null;
try{
logger.debug(springAopAspect-before【前置通知】,正在增强:+methodInvocation.getMethod().getName()+方法);
ret =methodInvocation.proceed();//执行下一个方法
logger.debug(springAopAspect-afterReturning【后置通知】,正在增强:+methodInvocation.getMethod().getName()+方法);
}catch (Exception o){
logger.debug(springAopAspect-exception【异常通知】,正在增强:+methodInvocation.getMethod().getName()+方法);
logger.debug(异常信息:+o.getMessage());
}finally {
logger.debug(springAopAspect-return【最终通知】,正在增强:+methodInvocation.getMethod().getName()+方法);
}
return ret;
}
//前置增强回调方法
/* @Override
public void before(Method method,//目标方法对象
Object[]objects,//方法参数
Object o) throwsThrowable {
logger.debug(springAopAspect-before【前置通知】,正在增强:+method.getName()+方法,所带的参数为:+objects);
}*/
//后置增强回调方法
/*@Override
public void afterReturning(Objecto,
Methodmethod,
Object[]objects,
Objecto1) throws Throwable {
logger.debug(springAopAspect-afterReturning【后置通知】,正在增强:+method.getName()+方法,返回值:+o);
}*/
}
2.配置bean
!--被代理的bean--
bean id=userServiceBean
lazy-init=false class=org.fjh.service.impl.UserServiceBean
/bean
!--增强bean--
bean id=springAopAspectBean class=org.fjh.aop.SpringAopAspect/
3.配置增强代理bean,和代理对象的生成bean
!--增强者bean(切入点)--
bean id=aspectBean class=org.springframework.aop.support.RegexpMethodPointcutAdvisor
!--使用正则表达式,指定增强(通知)的规则--
property name=pattern
value=org\.fjh\.service\.impl\..*/
!--增强处理器--
property name=advice
ref bean=springAopAspectBean/
/property
/bean
!--使用proxyFactoryBean生成代理对象--
bean id=userServiceproxyBean class=org.springframework.aop.framework.ProxyFactoryBean
!--指定接口--
property name=interfaces
valueorg.fjh.service.IUserServiceBean/value
/property
!--指定被代理的对象--
property name=target ref=userServiceBean /
!--指定切入点--
property name=interceptorNames
valueaspectBean/value
/property
/bean
4.取得代理bean
@Test
public void springAopTest(){
//取得代理后的bean
IUserServiceBean bean= (IUserServiceBean)ctx.getBean(userServiceproxyBean);
bean.updateUser();
}
4.AspectJ
可使用xml和注解方式都可实现aop
4.1.Xml的方式4.1.1.实现步骤
1.引入aspectJ的依赖
在pom.xml中加入
!--
dependency
groupIdorg.aspectj/groupId
artifactIdaspectjrt/artifactId
version1.9.4/version
/dependency
!--
dependency
groupIdorg.aspectj/groupId
artifactIdaspectjweaver/artifactId
version1.9.4/version
/dependency
2.编写切面类
public class AspectJAspect {
private Logger logger = LoggerFactory.getLogger(AspectJAspect.class);
//实现5个增强通知的方法
private void beforeHandler(JoinPoint jp){
Stringname=jp.getTarget().getClass().getSimpleName();
StringmethodName=jp.getSignature().getName();
Object args = jp.getArgs();
String str=被增加的类型:+name+,增加的方法名:+methodName+,参数:+args;
logger.debug(AspectJAspect--【前置通知】:+str);
}
private void afterHandler(JoinPoint jp){
logger.debug(AspectJAspect--【最终通知】:增加的方法名:+jp.getSignature().getName());
}
private void afteringHandler(JoinPoint jp,Objectret){
logger.debug(AspectJAspect--【后置通知】:增强的方法名:+jp.getSignature().getName()+,返回值:+ret);
}
private void exceptionHandler(JoinPoint jp,Exceptionex){
logger.debug(AspectJAspect--【异常通知】:增强的方法名:+jp.getSignature().getName());
logger.debug(AspectJAspect--【异常信息】:+ex.getMessage());
}
private Object around(ProceedingJoinPoint pjp)throws Throwable{
Object ret = pjp.proceed();//调用下一个方法
logger.debug(AspectJAspect--【环绕通知】:+pjp.getSignature().getName());
return ret;
}
}
3.加入aop的命名空间
在applicationContext.xml中加入aop的命名空间
?xml version=1.0 encoding=UTF-8?
beans xmlns=
xmlns:xsi=
xmlns:aop=
xsi:schemaLocation=
4.配置aop
!--aspectJ切面类--
bean id=aspectJaspectBeanclass=org.fjh.aop.AspectJAspect/
!--配置aop--
aop:config
!--定义切入点--
aop:pointcut id=mypointcut expression=execution(* org.fjh.service..*(..)) /
!--增强切面
ref:引用以定义的切面类bean--
aop:aspect ref=aspectJaspectBean
!--
method:切面中处理方法
pointcut:切入点规则
pointcut-ref:引用以定义的规则
--
aop:before method=beforeHandler pointcut-ref=mypointcut/
aop:around method=around pointcut-ref=mypointcut/
!--
returning:返回方法的参数名称(用于接收目标方法返回值)
--
aop:after-returning method=afteringHandler pointcut-ref=mypointcut returning=ret/
!--
throwing:异常处理方法的参数名称(用于接收目标方法执行过程抛出的异常)
--
aop:after-throwing method=exceptionHandler pointcut-ref=mypointcut throwing=ex /
aop:after method=afterHandler pointcut-ref=mypointcut/
/aop:aspect
/aop:config
/beans
5.取得bean
@Test
public void aspectJTest()
{
IUserServiceBean bean =(IUserServiceBean) ctx.getBean(userServiceBean);
bean.addUser(rose);
}
4.2.注解方式4.2.1.实现步骤
1.引入aspectJ的依赖
!--
dependency
groupIdorg.aspectj/groupId
artifactIdaspectjrt/artifactId
version1.9.4/version
/dependency
!--
dependency
groupIdorg.aspectj/groupId
artifactIdaspectjweaver/artifactId
version1.9.4/version
/dependency
2.编写aspect处理类
@Aspect //告诉spring此类是一个切面类
@Component//标识本类是个组件
publicclass AspectJAspectAno {
private Logger logger = LoggerFactory.getLogger(AspectJAspectAno.class);
//定义切入点
@Pointcut(execution(*org.fjh.service..*(..)))
private void mypointcut(){}
//实现5个增强通知的方法
//mypointcut()是以定义的切入点
@Before(value = mypointcut())
private void beforeHandler(JoinPoint jp){
Stringname=jp.getTarget().getClass().getSimpleName();
StringmethodName=jp.getSignature().getName();
Object args = jp.getArgs();
String str=被增加的类型:+name+,增加的方法名:+methodName+,参数:+args;
logger.debug(AspectJAspectAno--【前置通知】:+str);
}
@After(value = mypointcut())
private void afterHandler(JoinPoint jp){
logger.debug(AspectJAspectAno--【最终通知】:增加的方法名:+jp.getSignature().getName());
}
@AfterReturning(value = mypointcut(), returning = ret)
private void afteringHandler(JoinPoint jp,Objectret){
logger.debug(AspectJAspectAno--【后置通知】:增强的方法名:+jp.getSignature().getName()+,返回值:+ret);
}
@AfterThrowing(value = mypointcut(),throwing = ex)
private void exceptionHandler(JoinPoint jp,Exceptionex){
logger.debug(AspectJAspectAno--【异常通知】:增强的方法名:+jp.getSignature().getName());
logger.debug(AspectJAspectAno--【异常信息】:+ex.getMessage());
}
@Around(mypointcut())
private Object around(ProceedingJoinPoint pjp)throws Throwable{
Object ret = pjp.proceed();//调用下一个方法
logger.debug(AspectJAspectAno--【环绕通知】:+pjp.getSignature().getName());
return ret;
}
}
3.引入aop,context命名空间
?xml version=1.0 encoding=UTF-8?
beans xmlns=
xmlns:xsi=
xmlns:aop=
xmlns:context=
xsi:schemaLocation=
4.设定bean的扫描路径
!--设定扫描包的路径 --
context:component-scan base-package=org.fjh/
5.设定aspectJ自动代理
!--使用aspectJ自动代理
proxy-target-class:采用JDK动态代理还是cglib
true:cglib方式
false:jdk动态代理(默认)
一般不设定,因新版本aspectJ会自动识别--
aop:aspectj-autoproxy proxy-target-class=false /
6.取得bean
@Test
public void aspectJTest()
{
IUserServiceBean bean =(IUserServiceBean) ctx.getBean(userServiceBean);
bean.addUser(rose);
}
注意:
采用注解的通知执行顺序
前置-环绕-最终-后置(没有异常)
前置-环绕-异常-后置(发生异常)
解决方案:
将其它4种增强(通知)的代码都放在环绕通知中
@Around(mypointcut())
private Objectaround(ProceedingJoinPoint pjp)throws Throwable{
Object ret = null;
try {
//前置增强码
ret = pjp.proceed();//调用下一个方法
//后置增强代码
} catch (Exception o)
{
//异常增强代码
} finally {
//最终增强代码
}
}
以上就是(Spring框架 spring-aop (spring框架的优点))全部内容,收藏起来下次访问不迷路!