Spring AOP 全自动编程

来源:互联网 发布:淘宝有卖写真集 编辑:程序博客网 时间:2024/04/28 11:08

SpringAOP 全自动编程


1、什么是AOP

     AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

     AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码。Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码。

2、什么是AspectJ

        AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入。

3、AOP实现原理

       1、aop底层将采用代理机制进行实现。

       2、接口 + 实现类 :spring采用 jdk的动态代理Proxy。

       3、实现类:spring 采用 cglib字节码增强。

4、AOP术语

1.target:目标类,需要被代理的类。例如:UserService

2.Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法

3.PointCut 切入点:已经被增强的连接点。例如:addUser()

4.advice 通知/增强,增强代码。例如:after、before

5. Weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程.

6.proxy 代理类

7.Aspect(切面): 是切入点pointcut和通知advice的结合。 一个线是一个特殊的面。     一个切入点和一个通知,组成成一个特殊的面。

 

5、CGLIB字节码增强

    没有接口,只有实现类。采用字节码增强框架 cglib,在运行时创建目标类的子类,从而对目标类进行增强。

6、AOP联盟通知类型

      Spring按照通知Advice在目标类方法的连接点位置,可以分为5类

     1、前置通知 org.springframework.aop.MethodBeforeAdvice:在目标方法执行前实施增强

      2、后置通知 org.springframework.aop.AfterReturningAdvice:在目标方法执行后实施增强

      3、环绕通知 org.aopalliance.intercept.MethodInterceptor:在目标方法执行前后实施增强。必须手动执行目标方法。

      4、异常抛出通知 org.springframework.aop.ThrowsAdvice:在方法抛出异常后实施增强

      5、引介通知 org.springframework.aop.IntroductionInterceptor:在目标类中添加一些新的方法和属性【略】

【注意】环绕通知的格式为:

try{   //前置通知【前置通知可以阻止执行目标方法】   //执行目标方法   //后置通知【后置通知可以获得目标方法的返回值】} catch(){   //抛出异常通知}


7、Spring AOP 全自动编程

原理:从Spring容器获得目标类,如果配置AOP,Spring将自动生成代理。

步骤:

1、导入Jar包:

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

spring-aop-3.2.0.RELEASE.jar

2、编写接口 interface UserService

public interface UserService {public void add();public void update();public void delete();}


3、编写接口的实现类 UserServiceImpl

public class UserServiceImpl implements UserService {/* (non-Javadoc) * @see com.Lily.SpringLearning.g_SpringAOP.UserService#add() */@Overridepublic void add() {// TODO Auto-generated method stubSystem.out.println("AOP Add() " +this.getClass().toString());}/* (non-Javadoc) * @see com.Lily.SpringLearning.g_SpringAOP.UserService#update() */@Overridepublic void update() {// TODO Auto-generated method stubSystem.out.println("AOP Update() "+this.getClass().toString());}/* (non-Javadoc) * @see com.Lily.SpringLearning.g_SpringAOP.UserService#delete() */@Overridepublic void delete() {// TODO Auto-generated method stubSystem.out.println("AOP Delete() "+this.getClass().toString());}}


4、编写切面类 LilyAspect

   【这里要确定通知的类型,实现对应的接口】这里注意,采用的是环绕通知的方法,所以要实现MethodInterceptor,这个接口在两个Jar包都有,添加的时候注意是org.aopalliance.intercept.MethodInterceptor 这个。

   还有invoke方法中要记得手动执行目标方法:

//手动执行目标方法

            Objectobj=arg0.proceed();

/** *  */package com.Lily.SpringLearning.g_SpringAOP;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;/**  * *  * @author   LilyLee * @date     2017年6月22日 * @time     上午9:50:29 * @Version  1.0 * @email    lilylee_1213@foxmail.com * */public class LilyAspect implements MethodInterceptor {/* (non-Javadoc) * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation) */@Overridepublic Object invoke(MethodInvocation arg0) throws Throwable {// TODO Auto-generated method stubSystem.out.println("环绕通知——前方法 ");//手动执行目标方法Object obj=arg0.proceed();System.out.println("环绕通知——后方法 ");return obj;}}



5、配置xml

头部新增:

xmlns:aop=http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd


编写内容

1、创建目标类

<beanid="?" class="?"></bean>

2、创建切面类

<beanid="?(Aspect)" class="?"></bean>

3、AOP编程【导入命名空间、config配置、切入点表达式】

<aop:config proxy-target-class="true">         <aop:pointcut expression="execution(* com.Lily_spring_aop.*.*(..))"id="myPointCut"/>        <aop:advisor advice-ref="AspectId" pointcut-ref="myPointCut"/></aop:config>


*这里 true是声明使用CGLIB代理

*切入点表达式 execution(* com.itheima.c_spring_aop.*.*(..))

execution(*com.Lily.Spring.*.*(..))选择方法返回值任意包名类名任意方法名任意参数任意

<aop:advisor>特殊的切面,只有一个通知 和 一个切入点

advice-ref 通知引用

pointcut-ref 切入点引用

<?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.g_SpringAOP.UserServiceImpl"></bean><bean id="LilyAspectId" class="com.Lily.SpringLearning.g_SpringAOP.LilyAspect"></bean><aop:config proxy-target-class="true"><aop:pointcut expression="execution(* com.Lily.SpringLearning.g_SpringAOP.*.*(..))" id="myPointCut"/><aop:advisor advice-ref="LilyAspectId" pointcut-ref="myPointCut"/></aop:config></beans>


6、编写测试类

 

public class Test {@org.junit.Testpublic void test() {String xmlPath = "com/Lily/SpringLearning/g_SpringAOP/beans.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);//获得目标类UserService u = (UserService) applicationContext.getBean("userServiceId");u.add();u.delete();u.update();}}


报错:

org.springframework.beans.factory.NoSuchBeanDefinitionException:No bean named 'userServiceId' is defined

      atorg.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:549)

      atorg.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1096)

      atorg.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:278)

      atorg.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)

      atorg.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1117)

      atcom.Lily.SpringLearning.g_SpringAOP.Test.test(Test.java:28)

      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)

在bean的配置里面写错了“userSerciveId”

Spring出错,90%都是配置文件的锅啊!!

原创粉丝点击