AspectJ 基于xml开发和基于注解的开发

AspectJ

1、概念

AspectJ是一个基于Java语言的AOP框架。Spring2.0以后新增了对AspectJ切点表达式支持。@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面。新版本Spring框架,建议使用AspectJ方式来开发AOP。主要用途:自定义开发。

2、切入点表达式

表达式execution(*com.Lily.spring_aop.*.*(..))

      语法:execution(修饰符  返回值  包.类.方法名(参数) throws异常)

      修饰符【一般省略】:public  *(任意)

      返回值【不能省略】:void  String *(任意)

     

            1、固定包com.Lily. aop

            2、aop包下的所有包,包括自己,包括孙包 com.Lily.aop..

            3、aop包下任意子包,固定目录Service,Service目录任意包 com.Lily.aop.*.Service..

      【一般省略】

            1、UserServiceImpl             指定类

            2、 *Impl                           以Impl结尾

            3、 User*                           以User开头

            4、 *                                 任意

      方法名【不能省略】

            1、addUser                        固定方法

            2、 add*                                  以add开头

            3、 *Do                             以Do结尾

            4、 *                                  任意

      参数

            1、 ()                                 无参

            2、 (int)                             一个整型

            3、 (int ,int)                        两个

            4、 (..)                               参数任意

异常【可省略,一般不写】

3、AspectJ通知类型

AOP联盟定义了6种通知类型,具有特性接口,必须实现对应的接口,从而确定方法名称。

1.      before:前置通知(应用:各种校验):在方法执行前执行,如果通知抛出异常,阻止方法运行。

2.      afterReturning:后置通知(应用:常规数据处理):方法正常返回后执行,如果方法中抛出异常,通知无法执行。必须在方法执行后才执行,所以可以获得方法的返回值。

3.      around:环绕通知(应用:十分强大,可以做任何事情):方法执行前后分别执行,可以阻止方法的执行。  必须手动执行目标方法

4.      afterThrowing:抛出异常通知(应用:包装异常信息):方法抛出异常后执行,如果方法没有抛出异常,无法执行。

5.      after:最终通知(应用:清理现场):方法执行完毕后执行,无论方法中是否出现异常。

4、基于xml的aop编程

1、导入Jar包

【前面AOP的包和Spring的4+1包都是默认导入】

spring-aspects-3.2.0.RELEASE.jar

2、编写UserService接口

public interface UserService {
	public void addUser();
	public String updateUser();
	public void deleteUser();
}


3、编写接口的实现类

public class UserSerImpl implements UserService {

	/* (non-Javadoc)
	 * @see com.Lily.SpringLearning.h_AspectJ.UserService#addUser()
	 */
	@Override
	public void addUser() {
		// TODO Auto-generated method stub
System.out.println("AspectJ  add() "+this.getClass().getName());
	}

	/* (non-Javadoc)
	 * @see com.Lily.SpringLearning.h_AspectJ.UserService#updateUser()
	 */
	@Override
	public String updateUser() {
		// TODO Auto-generated method stub
		System.out.println("AspectJ  update() "+this.getClass().getName());
		//引入Exeception
		int i=1/0;
		
		return "See my Error?";
	}

	/* (non-Javadoc)
	 * @see com.Lily.SpringLearning.h_AspectJ.UserService#deleteUser()
	 */
	@Override
	public void deleteUser() {
		// TODO Auto-generated method stub
		System.out.println("ASpectJ  delete()  ");
	}

}


4、切面类

这里将上述的5中通知类型都写入了,需要哪种就用哪种。【一般要求掌握的是环绕通知,因为有前有后,但是还是要根据实际的需求来定】

public class LilyAspcet {
	
	public void LilyBefore(JoinPoint jp){
		System.out.println("前置通知:  "+jp.getSignature().getName());		
	}
	
	public void LilyAfterReturning(JoinPoint jp,Object obj){
		System.out.println("后置通知:  "+jp.getSignature().getName()+" → "+obj);		
	}	
	
	
	public Object LilyAround(ProceedingJoinPoint jp)throws Throwable{
		System.out.println("around的前方法");
		//手动执行目标方法
		Object obj=jp.proceed();
		System.out.println("around的后方法");
		return obj;
		
	}
	
	public void LilyAfterThrowing(JoinPoint jp,Throwable e){
		System.out.println("抛出异常通知 "+e.getMessage());
	}
	
	public void LilyAfter(JoinPoint jp){
		System.out.println("一定会出现的 最 终  通  知 ~");
	}
	

}


5、编写bean.xml

【这里要注意,不能同时使用多个通知类型,使用哪个就写哪个,举例是前置通知,其他的通知就将<aop:??method="" pointcut-ref="myPointCut"/>的方法名改成对应的方法名即可】

前置通知 <aop:before method="LilyBefore" pointcut-ref="myPointCut"/>

后置通知 <aop:after-returning method="LilyAfterReturning"pointcut-ref="myPointCut" returning="obj"/>

环绕通知 <aop:around method="LilyAround"pointcut-ref="myPointCut"/>

抛出异常 <aop:after-throwing method="LilyAfterThrowing" pointcut-ref="myPointCut"throwing="e"/>

最终通知  <aop:after method="LilyAfter"pointcut-ref="myPointCut"/>

<?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-4.3.xsd
       					   http://www.springframework.org/schema/aop 
       					   http://www.springframework.org/schema/aop/spring-aop.xsd">
	
	
	
	<bean id="userServiceId" class="com.Lily.SpringLearning.h_AspectJ.UserSerImpl"></bean>
	
	<bean id="LilyAspect" class="com.Lily.SpringLearning.h_AspectJ.LilyAspcet"></bean>
	
	<aop:config>
		<aop:aspect ref="LilyAspect">
			<aop:pointcut expression="execution(* com.Lily.SpringLearning.h_AspectJ.UserSerImpl.*(..))" id="myPointCut"/>
			<!--aop:before method="LilyBefore" pointcut-ref="myPointCut"/>-->
			<!--aop:after-returning method="LilyAfterReturning" pointcut-ref="myPointCut" returning="obj"/>-->
			<!--aop:around method="LilyAround" pointcut-ref="myPointCut"/>-->
			<aop:after-throwing method="LilyAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
			<!--aop:after method="LilyAfter" pointcut-ref="myPointCut"/>  -->
			
		
		</aop:aspect>	
	</aop:config>	
	
</beans>


6、编写测试类

 

public class TestAspectJ {

	@Test
	public void test() {
		String xmlPath = "com/Lily/SpringLearning/h_AspectJ/beans.xml";
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
		
		//获得目标类
		UserService userService = (UserService) applicationContext.getBean("userServiceId");
		userService.addUser();
		userService.updateUser();
		userService.deleteUser();
	}

}

5、基于注解的aop编程

1、需要在实现类上添加注解 @Service("userServiceId")

@Service("userServiceId")
public class UserSerImpl implements UserService {

	/* (non-Javadoc)
	 * @see com.Lily.SpringLearning.h_AspectJ.UserService#addUser()
	 */
	@Override
	public void addUser() {
		// TODO Auto-generated method stub
System.out.println("AspectJ  add() "+this.getClass().getName());
	}

	/* (non-Javadoc)
	 * @see com.Lily.SpringLearning.h_AspectJ.UserService#updateUser()
	 */
	@Override
	public String updateUser() {
		// TODO Auto-generated method stub
		System.out.println("AspectJ  update() "+this.getClass().getName());
		//引入Exeception
		int i=1/0;
		
		return "See my Error?";
	}

	/* (non-Javadoc)
	 * @see com.Lily.SpringLearning.h_AspectJ.UserService#deleteUser()
	 */
	@Override
	public void deleteUser() {
		// TODO Auto-generated method stub
		System.out.println("ASpectJ  delete()  ");
	}

}


2、需要修改Aspect类,最顶端添加注解@Component和@Aspect,在对应方法上声明切入点/前置通知/环绕通知/后置通知/抛出异常/最终通知。【注意,抛出异常的通知要写Throwable e,后置通知要注明returning="obj"】

@Component
@Aspect
public class LilyAspcet {
	
	//声明公共切入点,方便后续引用。若不声明,则每个通知需写自己的切入点表达式。
	@Pointcut("execution(* com.Lily.SpringLearning.h_AspectJ_anno.UserSerImpl.*(..))")
	private void myPonitCut(){}
	
	//@Before("execution(* com.Lily.SpringLearning.h_AspectJ_anno.UserSerImpl.*(..))")
	//@Before(value="myPonitCut()")
	public void LilyBefore(JoinPoint jp){
		System.out.println("前置通知:  "+jp.getSignature().getName());		
	}
	
//	@AfterReturning(value="myPonitCut()",returning="obj")
	public void LilyAfterReturning(JoinPoint jp,Object obj){
		System.out.println("后置通知:  "+jp.getSignature().getName()+" → "+obj);		
	}	
	
//	@Around (value="myPonitCut()")
	public Object LilyAround(ProceedingJoinPoint jp)throws Throwable{
		System.out.println("around的前方法");
		//手动执行目标方法
		Object obj=jp.proceed();
		System.out.println("around的后方法");
		return obj;
		
	}
	@AfterThrowing(value="myPonitCut()",throwing="e")
	public void LilyAfterThrowing(JoinPoint jp,Throwable e){
		System.out.println("抛出异常通知 "+e.getMessage());
	}
	//@After("myPonitCut()")
	public void LilyAfter(JoinPoint jp){
		System.out.println("一定会出现的 最 终  通  知 ~");
	}
	

}



3、在xml配置文件中,扫描注解类、并确定aop注解生效。

 

<?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:context="http://www.springframework.org/schema/context"
         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 
       					   http://www.springframework.org/schema/aop/spring-aop.xsd
       					   http://www.springframework.org/schema/context 
       					   http://www.springframework.org/schema/context/spring-context.xsd">
	
	
	
	<context:component-scan base-package="com.Lily.SpringLearning.h_AspectJ_anno"></context:component-scan>
	

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>


注解第一次报错

org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException:Line 13 in XML document from class path resource[com/Lily/SpringLearning/h_AspectJ_anno/beans.xml] is invalid; nested exceptionis org.xml.sax.SAXParseException; lineNumber: 13; columnNumber: 80;cvc-complex-type.2.4.c: 通配符的匹配很全面, 但无法找到元素 'context:component-scan' 的声明。

      atorg.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:396)

      atorg.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)

      atorg.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)

      atorg.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:174)

      atorg.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:209)

      atorg.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180)

      atorg.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:243)

      atorg.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:127)

      atorg.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:93)

      atorg.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:131)

      atorg.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:537)

      atorg.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:451)

      atorg.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)

      atorg.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)

      atcom.Lily.SpringLearning.h_AspectJ_anno.TestAspectJ.test(TestAspectJ.java:26)

      atsun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

      atsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)

      atsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

      atjava.lang.reflect.Method.invoke(Method.java:606)

      atorg.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)

      atorg.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)

      atorg.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)

      atorg.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)

      atorg.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)

      atorg.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)

      atorg.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)

      atorg.junit.runners.ParentRunner$3.run(ParentRunner.java:238)

      atorg.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)

      atorg.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)

      atorg.junit.runners.ParentRunner.access$000(ParentRunner.java:53)

      atorg.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)

      atorg.junit.runners.ParentRunner.run(ParentRunner.java:309)

      atorg.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)

      atorg.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)

      atorg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)

      atorg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)

      atorg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)

      atorg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Caused by: org.xml.sax.SAXParseException;lineNumber: 13; columnNumber: 80; cvc-complex-type.2.4.c: 通配符的匹配很全面, 但无法找到元素 'context:component-scan' 的声明。

      atcom.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)

      atcom.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)

      atcom.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437)

      atcom.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368)

      atcom.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325)

      atcom.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:458)

      atcom.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3237)

      atcom.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:1917)

      atcom.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:746)

      atcom.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:378)

      atcom.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2778)

      atcom.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)

      atcom.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117)

      atcom.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)

      atcom.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)

      atcom.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)

      atcom.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)

      atcom.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)

      atcom.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:347)

      atorg.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:75)

      atorg.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:388)

      ...37 more

 查了一下,xml文件忘记了添加

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd



AOP注解开发总结:

@Aspect 声明切面,修饰切面类,从而获得通知。

@PointCut,修饰方法 private void xxx(){},之后通过 方法名 获得切入点引用。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值