zoukankan      html  css  js  c++  java
  • Spring_Spring与AOP

    一、传统编程使用代理解决目标类增强问题

    1 //主业务接口
    2 public interface ISomeService {
    3     // 目标方法
    4     void doFirst();
    5     // 目标方法
    6     void doSecond();
    7 }
    ISomeService
     1 //目标类
     2 public class SomeServiceImpl implements ISomeService {
     3 
     4     @Override
     5     public void doFirst() {
     6         // TODO Auto-generated method stub
     7         System.out.println("执行doFirst()方法");
     8     }
     9 
    10     @Override
    11     public void doSecond() {
    12         System.out.println("执行doSecond()方法");
    13     }
    14 
    15 }
    SomeServiceImpl
     1 public class SystemService {
     2 
     3     public  static void doLog() {
     4         System.out.println("执行日志代码");
     5     }
     6 
     7     public  static void doTx() {
     8         System.out.println("执行事务代码");
     9     }
    10 }
    SystemService
     1 import java.lang.reflect.InvocationHandler;
     2 import java.lang.reflect.Method;
     3 import java.lang.reflect.Proxy;
     4 
     5 import com.jmu.service.ISomeService;
     6 import com.jmu.service.SomeServiceImpl;
     7 import com.jmu.utils.SystemService;
     8 
     9 public class MyTest {
    10 
    11     public static void main(String[] args) {
    12         // TODO Auto-generated method stub
    13         ISomeService target=new SomeServiceImpl();
    14         ISomeService service=(ISomeService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), new InvocationHandler() {
    15             //织入weaving:将系统级服务切入到主业务逻辑中
    16             @Override
    17             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    18                 // TODO Auto-generated method stub
    19                 SystemService.doTx();
    20                 //执行目标方法
    21                 Object result = method.invoke(target, args);
    22                 SystemService.doLog();
    23                 return result;
    24             }
    25         });
    26        service.doFirst();
    27        System.out.println("---------------");
    28        service.doSecond();
    29     }
    30 
    31 }
    MyTest

    二、AOP术语

    (1)切面(Aspect)

       切面泛指业务逻辑。常用的切面有通知(Advice)和顾问(Advisor)。实际上就是对主业务逻辑的一种增强。

    (2)织入(Weaving)

      织入指将切面代码插入到目标对象的过程。

    (3)连接点(JoinPoint)

     连接点指可以被切面织入的方法。通常业务接口中的方法均为连接点。

    (4)切入点(Pointcut)

     切入点指切面具体织入的方法。被标记为final的方法不能作为连接点和切点。

    (5)目标对象(Target)

    目标对象指将被增强的对象。

    (6)通知(Advice)

    通知是切面的一实现。,可以完成简单织入功能。通知定义了增强代码切入带目标代码的时间点,是目标方法执行之前执行,还是之后执行等。通知类型不同,切入的时间不同。

    切入点定义切入的位置,通知定义切入的时间。

    (7)顾问(Advisor)

     顾问是切面的另一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装置器。

    三、AOP编程环境的搭建

     四、通知(Advice)的详解

    (1)前置通知(MethodBeforeAdvice)

     1 import java.lang.reflect.Method;
     2 
     3 import org.springframework.aop.MethodBeforeAdvice;
     4 
     5 //前置通知
     6 public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
     7     // 当前方method:法在目标方法执行之前执行
     8     // method:目标方法
     9     // args:目标方法的参数列表
    10     // target:目标对象
    11     @Override
    12     public void before(Method method, Object[] args, Object target) throws Throwable {
    13         // TODO Auto-generated method stub
    14         // 对于目标方法增强的代码写于此
    15         System.out.println("执行前置通知方法");
    16     }
    17 
    18 }
    MyMethodBeforeAdvice
     1 <!-- 注册目标对象 -->
     2     <bean id="someService" class="com.jmu.aop01.SomeServiceImpl" />
     3 
     4     <!-- 注册切面:通知 -->
     5     <bean id="myAdvice" class="com.jmu.aop01.MyMethodBeforeAdvice" />
     6 
     7     <!-- 生成代理对象 -->
     8     <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
     9         <!-- <property name="targetName" ref="someService"></property> -->
    10         <!-- 指定目标对象 -->
    11         <property name="target" ref="someService"></property>
    12         <!-- 指定切面 -->
    13         <property name="interceptorNames" value="myAdvice"></property>
    14     </bean>
    applicationContext.xml
     1 import org.junit.Test;
     2 import org.springframework.context.ApplicationContext;
     3 import org.springframework.context.support.ClassPathXmlApplicationContext;
     4 
     5 public class MyTest {
     6 
     7     @Test
     8     public void test01() {
     9         //创建容器对象
    10         String resource = "com/jmu/aop01/applicationContext.xml";
    11         ApplicationContext ac=new ClassPathXmlApplicationContext(resource);
    12         ISomeService service=(ISomeService) ac.getBean("serviceProxy");
    13         service.doFirst();
    14         System.out.println("----------");
    15         service.doSecond();
    16     }
    17 
    18 }
    MyTest

    输出:

    执行前置通知方法
    执行doFirst()方法
    ----------
    执行前置通知方法
    执行doSecond()方法
    output

    (2)后置通知(AfterReturningAdvice)

    后置通知:可以获取到目标方法的返回结果,但无法改变目标方法的结果

    1 //主业务接口
    2 public interface ISomeService {
    3     // 目标方法
    4     void doFirst();
    5     // 目标方法
    6     String doSecond();
    7 }
    ISomeService
     1 //目标类
     2 public class SomeServiceImpl implements ISomeService {
     3 
     4     @Override
     5     public void doFirst() {
     6         // TODO Auto-generated method stub
     7         System.out.println("执行doFirst()方法");
     8     }
     9 
    10     @Override
    11     public String doSecond() {
    12         System.out.println("执行doSecond()方法");
    13      return "ABCD";
    14     }
    15 
    16 }
    SomeServiceImpl
     1 import java.lang.reflect.Method;
     2 //后置通知:可以获取到目标方法的返回结果,但无法改变目标方法的结果
     3 public class MyAfterReturningAdvice implements org.springframework.aop.AfterReturningAdvice {
     4     // 在目标方法之后执行
     5     // returnValue:目标方法的返回值
     6     @Override
     7     public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
     8         // TODO Auto-generated method stub
     9         System.out.println("执行后置通知方法 reurnValue= "+returnValue);
    10         if (returnValue!=null) {
    11             returnValue = ((String) returnValue).toLowerCase();
    12             System.out.println("修改过的结果returnValue="+returnValue);
    13         }
    14     }
    15 
    16 }
    MyAfterReturningAdvice
     1 <!-- 注册目标对象 -->
     2     <bean id="someService" class="com.jmu.aop02.SomeServiceImpl" />
     3 
     4     <!-- 注册切面:通知 -->
     5     <bean id="myAdvice" class="com.jmu.aop02.MyAfterReturningAdvice" />
     6 
     7     <!-- 生成代理对象 -->
     8     <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
     9         <property name="target" ref="someService"></property>
    10         <property name="interceptorNames" value="myAdvice"></property>
    11     </bean>
    applicationContext.xml
     1 import org.junit.Test;
     2 import org.springframework.context.ApplicationContext;
     3 import org.springframework.context.support.ClassPathXmlApplicationContext;
     4 
     5 public class MyTest {
     6 
     7     @Test
     8     public void test01() {
     9         //创建容器对象
    10         String resource = "com/jmu/aop02/applicationContext.xml";
    11         ApplicationContext ac=new ClassPathXmlApplicationContext(resource);
    12         ISomeService service=(ISomeService) ac.getBean("serviceProxy");
    13         service.doFirst();
    14         System.out.println("----------");
    15         String result = service.doSecond();
    16         System.out.println(result);
    17     }
    18 
    19 }
    MyTest

    输出:

    执行doFirst()方法
    执行后置通知方法 reurnValue= null
    ----------
    执行doSecond()方法
    执行后置通知方法 reurnValue= ABCD
    修改过的结果returnValue=abcd
    output

    (3)环绕通知(MethodInterceptor)

    环绕通知:可以修改目标方法的返回结果

     1 import org.aopalliance.intercept.MethodInterceptor;
     2 import org.aopalliance.intercept.MethodInvocation;
     3 //环绕通知:可以修改目标方法的返回结果
     4 public class MyMethodIntercepter implements MethodInterceptor {
     5 
     6     @Override
     7     public Object invoke(MethodInvocation invocation) throws Throwable {
     8         // TODO Auto-generated method stub
     9         System.out.println("执行环绕通知:目标方法执行之前");
    10         //执行目标方法
    11         Object result = invocation.proceed();
    12         System.out.println("执行环绕通知:目标方法执行之后");
    13         if (result!=null) {
    14             result=((String)result).toLowerCase();
    15         }
    16         return result;
    17     }
    18 
    19 }
    MyMethodIntercepter

    输出:

    1 执行环绕通知:目标方法执行之前
    2 执行doFirst()方法
    3 执行环绕通知:目标方法执行之后
    4 ----------
    5 执行环绕通知:目标方法执行之前
    6 执行doSecond()方法
    7 执行环绕通知:目标方法执行之后
    8 abcd
    output

     (4)异常通知(ThrowsAdvice)

    a、

    异常分2种:

    1. 运行时异常,不进行处理,也可以通过编译。若一个类继承自RunTimeException,则该异常就是运行时异常
    2. 编译时异常(受查异常 Checked Exception),不进行处理,不能通过编译。若一个类继承自Exception,则该异常就是受查异常

    1 import org.springframework.aop.ThrowsAdvice;
    2 
    3 public class MyThrowsAdvice implements ThrowsAdvice {
    4 
    5     //当目标方法抛出与指定类型的异常具有is-a关系的异常时,执行当前方法
    6     public void afterThrowing(Exception ex) {
    7         System.out.println("执行异常通知方法");
    8     }
    9 }
    MyThrowsAdvice
    1 @Override
    2     public void doFirst() {
    3         // TODO Auto-generated method stub
    4         System.out.println("执行doFirst()方法"+3/0);
    5     }
    SomeServiceImpl

    输出:

    执行异常通知方法
    output

    b、捕获自定义异常

     1 public class UserException extends Exception {
     2 
     3     public UserException() {
     4         super();
     5         // TODO Auto-generated constructor stub
     6     }
     7 
     8     public UserException(String message) {
     9         super(message);
    10         // TODO Auto-generated constructor stub
    11     }
    12   
    13 }
    UserException
     1 public class UsernameException extends UserException {
     2 
     3     public UsernameException() {
     4         super();
     5         // TODO Auto-generated constructor stub
     6     }
     7 
     8     public UsernameException(String message) {
     9         super(message);
    10         // TODO Auto-generated constructor stub
    11     }
    12 
    13 }
    UsernameException
     1 public class PasswordException extends UserException {
     2 
     3     public PasswordException() {
     4         super();
     5         // TODO Auto-generated constructor stub
     6     }
     7 
     8     public PasswordException(String message) {
     9         super(message);
    10         // TODO Auto-generated constructor stub
    11     }
    12 
    13 }
    PasswordException
    1 //主业务接口
    2 public interface ISomeService {
    3     // 目标方法
    4     boolean login(String username,String password)throws UserException;
    5 
    6 }
    ISomeService
     1 public class SomeServiceImpl implements ISomeService {
     2 
     3     @Override
     4     public boolean login(String username, String password) throws UserException {
     5         // TODO Auto-generated method stub
     6         if(!"Jane".equals(username)){
     7              throw new UsernameException("用户名输入错误!");
     8         }
     9         if(!"aaa".equals(password)){
    10              throw new PasswordException("密码输入错误!");
    11         }
    12     /*    double a=3/0;*/
    13         return true;
    14     }
    15 
    16 }
    SomeServiceImpl
     1 import org.springframework.aop.ThrowsAdvice;
     2 
     3 public class MyThrowsAdvice implements ThrowsAdvice {
     4 
     5     // 当目标方法抛出UsernameException异常时,执行当前方法
     6     public void afterThrowing(UsernameException ex) {
     7         System.out.println("发生用户名异常 ex=" + ex.getMessage());
     8     }
     9 
    10     // 当目标方法抛出PasswordException异常时,执行当前方法
    11     public void afterThrowing(PasswordException ex) {
    12         System.out.println("发生密码异常 ex=" + ex.getMessage());
    13     }
    14     
    15     // 当目标方法抛出其他异常时,执行当前方法
    16     public void afterThrowing(Exception ex) {
    17         System.out.println("发生异常 ex=" + ex.getMessage());
    18     }
    19     
    20 }
    MyThrowsAdvice
     1 import org.junit.Test;
     2 import org.springframework.context.ApplicationContext;
     3 import org.springframework.context.support.ClassPathXmlApplicationContext;
     4 
     5 public class MyTest {
     6 
     7     @Test
     8     public void test01() throws UserException{
     9         //创建容器对象
    10         String resource = "com/jmu/aop05/applicationContext.xml";
    11         ApplicationContext ac=new ClassPathXmlApplicationContext(resource);
    12         ISomeService service=(ISomeService) ac.getBean("serviceProxy");
    13         service.login("gad", "aaa");
    14     }
    15 
    16 }
    MyTest

    测试:

      service.login("gad", "aaa");

    输出:

    发生用户名异常 ex=用户名输入错误!

    在SomeServiceImpl中加入

    double a=3/0;

    输出:

    发生异常 ex=/ by zero

    c、异常的两种处理方式

    控制台输出异常

     1 public class MyTest {
     2 
     3     @Test
     4     public void test01() {
     5         //创建容器对象
     6         String resource = "com/jmu/aop05/applicationContext.xml";
     7         ApplicationContext ac=new ClassPathXmlApplicationContext(resource);
     8         ISomeService service=(ISomeService) ac.getBean("serviceProxy");
     9         try {
    10             service.login("Jane", "111");
    11         } catch (UserException e) {
    12             // TODO Auto-generated catch block
    13             e.printStackTrace();
    14         }
    15     }
    16 
    17 }
    MyTest

    虚拟机不通过

     1 import org.junit.Test;
     2 import org.springframework.context.ApplicationContext;
     3 import org.springframework.context.support.ClassPathXmlApplicationContext;
     4 
     5 public class MyTest {
     6 
     7     @Test
     8     public void test01() throws UserException{
     9         //创建容器对象
    10         String resource = "com/jmu/aop05/applicationContext.xml";
    11         ApplicationContext ac=new ClassPathXmlApplicationContext(resource);
    12         ISomeService service=(ISomeService) ac.getBean("serviceProxy");
    13         service.login("Jane", "1111");
    14     }
    15 
    16 }
    MyTest

    五、为目标方法织入多个通知

     1 <!-- 注册目标对象 -->
     2     <bean id="someService" class="com.jmu.aop06.SomeServiceImpl" />
     3 
     4     <!-- 注册切面:通知 -->
     5     <bean id="myBeforeAdvice" class="com.jmu.aop06.MyMethodBeforeAdvice" />
     6     <bean id="myAfterAdvice" class="com.jmu.aop06.MyAfterReturningAdvice" />
     7 
     8     <!-- 生成代理对象 -->
     9     <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    10         <property name="target" ref="someService"></property>
    11         <property name="interceptorNames" value="myBeforeAdvice,myAfterAdvice"></property>
    12         
    13         <!-- <property name="interceptorNames">
    14             <array>
    15                 <value>myBeforeAdvice</value>
    16                 <value>myAfterAdvice</value>
    17             </array>
    18         </property> -->
    19     </bean>
    applicationContext

    六、无接口使用CGLIB代理

    之前

     1 //目标类
     2 public class SomeService {
     3 
     4     public void doFirst() {
     5         // TODO Auto-generated method stub
     6         System.out.println("执行doFirst()方法");
     7     }
     8 
     9     public String doSecond() {
    10         System.out.println("执行doSecond()方法");
    11         return "ABCD";
    12     }
    13 
    14 }
    SomeService
     1 <!-- 注册目标对象 -->
     2     <bean id="someService" class="com.jmu.aop07.SomeService" />
     3 
     4     <!-- 注册切面:通知 -->
     5     <bean id="myAdvice" class="com.jmu.aop07.MyAfterReturningAdvice" />
     6 
     7     <!-- 生成代理对象 -->
     8     <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
     9         <property name="target" ref="someService"></property>
    10         <property name="interceptorNames" value="myAdvice"></property>
    11     </bean>
    applicationContext
     1 import org.junit.Test;
     2 import org.springframework.context.ApplicationContext;
     3 import org.springframework.context.support.ClassPathXmlApplicationContext;
     4 
     5 public class MyTest {
     6 
     7     @Test
     8     public void test01() {
     9         //创建容器对象
    10         String resource = "com/jmu/aop07/applicationContext.xml";
    11         ApplicationContext ac=new ClassPathXmlApplicationContext(resource);
    12         SomeService service=(SomeService) ac.getBean("serviceProxy");
    13         service.doFirst();
    14         System.out.println("----------");
    15         String result = service.doSecond();
    16         System.out.println(result);
    17     }
    18 
    19 }
    MyTest

    七、有接口(也可以)使用CGLIB

    方法一:

    方法二:

     八、顾问 Advisor

    通知是Spring提供的一种切面,只能将切面织入到目标方法的所有方法中。

    顾问是Spring提供的另一种切面,其可以完成更为复杂的切面织入功能。

    PointAdisor是顾问的一种,可以指定具体的切入点。顾问将通知进行了包装,会根据不同的通知类型,在不同的时间点,将切面织入到不同的切入点。

    名称匹配方法切入点顾问

     1 public class SomeServiceImpl implements ISomeService {
     2 
     3     @Override
     4     public void doFirst() {
     5         // TODO Auto-generated method stub
     6         System.out.println("执行doFirst()方法");
     7     }
     8 
     9     @Override
    10     public String doSecond() {
    11         System.out.println("执行doSecond()方法");
    12      return "ABCD";
    13     }
    14 
    15     @Override
    16     public void doThird() {
    17         // TODO Auto-generated method stub
    18         System.out.println("执行doThird()方法");
    19     }
    20 
    21     
    22 }
    SomeServiceImpl
     1 <!-- 注册目标对象 -->
     2     <bean id="someService" class="com.jmu.aop09.SomeServiceImpl" />
     3 
     4     <!-- 注册切面:通知-->
     5     <bean id="myAdvice" class="com.jmu.aop09.MyAfterReturningAdvice" />
     6     <!-- 注册切面:顾问-->
     7     <bean id="myAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
     8       <property name="advice" ref="myAdvice"></property>
     9       <!-- 指定切入点 -->
    10       <!--   <property name="mappedName" value="doFirst"></property> -->
    11        <!-- <property name="mappedNames" value="doFirst,doSecond"></property> -->
    12        <property name="mappedNames" value="*ir*"></property>
    13     </bean>
    14     <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    15         <property name="target" ref="someService"></property>
    16         <property name="interceptorNames" value="myAdvisor"></property>
    17     </bean>
    applicationContext

    指定切入点:这里匹配的对象是简单方法名

     <property name="mappedNames" value="*ir*"></property>

    输出:

    执行doFirst()方法
    执行后置通知方法 reurnValue= null
    ----------
    执行doSecond()方法
    ----------
    执行doThird()方法
    执行后置通知方法 reurnValue= null
    output

    正则表达式方法切入点顾问

    运算符 名称 意义
    . 点号 表示任意单个字符
    + 加号 表示前一个字符出现一次或多次
    * 星号 表示前一个字符出现0次或多次 
     1 <!-- 注册目标对象 -->
     2     <bean id="someService" class="com.jmu.aop10.SomeServiceImpl" />
     3 
     4     <!-- 注册切面:通知-->
     5     <bean id="myAdvice" class="com.jmu.aop10.MyAfterReturningAdvice" />
     6     <!-- 注册切面:顾问-->
     7     <bean id="myAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
     8       <property name="advice" ref="myAdvice"></property>
     9       <!-- 这里的正则表达式匹配的对象是全限定方法名 -->
    10       <!--  <property name="pattern" value=".*doFirst"></property> -->
    11       <!-- <property name="patterns" value=".*doFirst,.*doSecond"></property> -->
    12       <property name="pattern" value=".*doFirst|.*doSecond"></property><!-- |为p右边的键,表示或 -->
    13     </bean>
    14     <bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    15         <property name="target" ref="someService"></property>
    16         <property name="interceptorNames" value="myAdvisor"></property>
    17     </bean>
    applicationContext

    这里正则表达式匹配的对象是全限定名

    <property name="pattern" value=".*S.*"></property>

    九、自动代理生成器

    前面代码中所使用的代理对象,均是由ProxyFactoryBean代理工具类生成的。该代理工具类存在如下缺点:

    1、一个代理对象只能代理一个Bean

    2、在客户类中获取Bean时。使用的是代理类id,而非我们定义的模目标对象Bea的id。

    Spring对此提供了自动代理生成器,常用的为以下2种:

    默认advisor自动代理器

        <!-- 注册自动代理生成器 -->
        <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
     1 public class MyTest {
     2 
     3     @Test
     4     public void test01() {
     5         // 创建容器对象
     6         String resource = "com/jmu/aop11/applicationContext.xml";
     7         ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
     8         ISomeService service = (ISomeService) ac.getBean("someService");
     9         service.doFirst();
    10         System.out.println("----------");
    11         service.doSecond();
    12         System.out.println("----------");
    13         service.doThird();
    14 
    15         System.out.println("--------------");
    16 
    17         ISomeService service2 = (ISomeService) ac.getBean("someService2");
    18         service2.doFirst();
    19         System.out.println("----------");
    20         service2.doSecond();
    21         System.out.println("----------");
    22         service2.doThird();
    23     }
    24 
    25 }
    MyTest

    输出:

    执行doFirst()方法
    执行后置通知方法 reurnValue= null
    ----------
    执行doSecond()方法
    ----------
    执行doThird()方法
    执行后置通知方法 reurnValue= null
    --------------
    执行doFirst()方法
    执行后置通知方法 reurnValue= null
    ----------
    执行doSecond()方法
    ----------
    执行doThird()方法
    执行后置通知方法 reurnValue= null
    output

    DefaultAdvisorAutoProxyCreator缺点:

    • 不能选择目标对象
    • 不能选择切面类型,切面只能是advisor
    • 不能选择advisor,所有advisor均被作文切面织入到目标

    Bean名称自动代理生成器

     1 <!-- 注册目标对象 -->
     2     <bean id="someService" class="com.jmu.aop12.SomeServiceImpl" />
     3     <bean id="someService2" class="com.jmu.aop12.SomeServiceImpl" />
     4     <!-- 注册切面:通知-->
     5     <bean id="myAdvice" class="com.jmu.aop12.MyAfterReturningAdvice" />
     6     <!-- 注册切面:顾问-->
     7     <bean id="myAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
     8       <property name="advice" ref="myAdvice"></property>
     9        <property name="mappedNames" value="doFirst"></property>
    10     </bean>
    11     <bean id="myAdvisor2" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
    12       <property name="advice" ref="myAdvice"></property>
    13        <property name="mappedNames" value="doSecond"></property>
    14     </bean>
    15     
    16     <!-- 注册自动代理生成器 -->
    17     <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    18        <property name="beanNames" value="someService"></property>
    19        <!--  <property name="interceptorNames" value="myAdvice"></property> -->
    20         <property name="interceptorNames" value="myAdvisor"></property>
    21     </bean>
    applicationContext
     1 public class MyTest {
     2 
     3     @Test
     4     public void test01() {
     5         // 创建容器对象
     6         String resource = "com/jmu/aop12/applicationContext.xml";
     7         ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
     8         ISomeService service = (ISomeService) ac.getBean("someService");
     9         service.doFirst();
    10         System.out.println("----------");
    11         service.doSecond();
    12         System.out.println("----------");
    13         service.doThird();
    14 
    15         System.out.println("--------------");
    16 
    17         ISomeService service2 = (ISomeService) ac.getBean("someService2");
    18         service2.doFirst();
    19         System.out.println("----------");
    20         service2.doSecond();
    21         System.out.println("----------");
    22         service2.doThird();
    23     }
    24 
    25 }
    MyTest

    输出:

    执行doFirst()方法
    执行后置通知方法 reurnValue= null
    ----------
    执行doSecond()方法
    ----------
    执行doThird()方法
    --------------
    执行doFirst()方法
    ----------
    执行doSecond()方法
    ----------
    执行doThird()方法
    output
  • 相关阅读:
    vue 爬坑之路---设置背景图,不能resolve编译
    vue 爬坑之路----flexible.js不适配ipad和ipad pro
    vue-cli3 vue.config.js配置
    vue组件
    Vue 路由按需keep-alive
    vue-cli项目搭建
    http和https
    js时间戳和日期互转换
    vue补充
    js实现头像上传(移动端,PC端均可)
  • 原文地址:https://www.cnblogs.com/hoje/p/8198768.html
Copyright © 2011-2022 走看看