1 静态代理

  • PersonDAO.java
package com.xuweiwei.staticproxy;

public interface PersonDAO {

    public void save();

}
  • PersonDAOImpl.java
package com.xuweiwei.staticproxy;

public class PersonDAOImpl implements PersonDAO {
    @Override
    public void save() {
        System.out.println("保存用户信息");
    }
}
  • Transaction.java
package com.xuweiwei.staticproxy;
//事务
public class Transaction {

    public void beginTransaction(){
        System.out.println("开启事务");
    }

    public void commit(){
        System.out.println("提交");
    }

}
  • PersonDAOProxyImpl.java
package com.xuweiwei.staticproxy;

public class PersonDAOProxyImpl implements PersonDAO {
    private PersonDAO personDAO;
    private Transaction transaction;
    public PersonDAOProxyImpl(PersonDAO personDAO,Transaction transaction){
        this.personDAO = personDAO;
        this.transaction = transaction;
    }

    @Override
    public void save() {
        this.transaction.beginTransaction();
        this.personDAO.save();
        this.transaction.commit();

    }
}
  • 测试
package com.xuweiwei.staticproxy;

import org.junit.Test;

public class TestStatic {

    @Test
    public void test(){
        PersonDAO personDAO = new PersonDAOImpl();
        Transaction transaction = new Transaction();
        PersonDAOProxyImpl proxy = new PersonDAOProxyImpl(personDAO,transaction);
        proxy.save();
    }

}
  • 缺点:

    • ①有多少DAO,就需要写多少proxy。
    • ②如果目标方法有方法的改动,proxy也需要做对应的缺点。

2 动态代理

2.1 JDK动态代理--基于接口的动态代理

  • PersonDAO.java
package com.xuweiwei.dynamicproxy;

public interface PersonDAO {

    public void save();

}
  • PersonDAOImpl.java
package com.xuweiwei.dynamicproxy;

public class PersonDAOImpl implements PersonDAO {
    @Override
    public void save() {
        System.out.println("保存用户信息");
    }
}
  • MyInterceptor.java
package com.xuweiwei.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInterceptor implements InvocationHandler {
    private Object target ;
    private Transaction transaction;

    public MyInterceptor(Object target, Transaction transaction) {
        this.target = target;
        this.transaction = transaction;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        this.transaction.beginTransaction();
        Object result = method.invoke(target,args);//调用目标类的目标方法
        this.transaction.commit();

        return result;
    }
}
  • Transaction.java
package com.xuweiwei.dynamicproxy;
//事务
public class Transaction {

    public void beginTransaction(){
        System.out.println("开启事务");
    }

    public void commit(){
        System.out.println("提交");
    }

}
  • 测试
package com.xuweiwei.dynamicproxy;

import org.junit.Test;

import java.lang.reflect.Proxy;

public class TestDynamic {

    @Test
    public void test(){
        PersonDAO personDAO = new PersonDAOImpl();
        Transaction transaction = new Transaction();

        PersonDAO proxy = (PersonDAO) Proxy.newProxyInstance(personDAO.getClass().getClassLoader(),personDAO.getClass().getInterfaces(),new MyInterceptor(personDAO,transaction));
        proxy.save();

    }
}
  • 问:拦截器中的invoke方法是在什么时候被调用的?
  • 答:在代理对象调用方法的时候,进入拦截器中的invoke()方法。
  • 问:拦截器中的method参数是什么?在什么时候由实参传递给形参?
  • 答:代理对象调用方法的名称是什么,method参数就是什么。代理对象调用方法的时候,进入拦截器中的invoke()方法的时候,传递参数。
  • 问:生成的代理对象实现了接口,代理对象的方法体的内容是什么?
  • 答:代理对象方法体的内容就是拦截器中invoke()方法体的内容。  
  • 可以在拦截器中对指定的方法进行判断
package com.xuweiwei.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInterceptor implements InvocationHandler {
    private Object target ;
    private Transaction transaction;

    public MyInterceptor(Object target, Transaction transaction) {
        this.target = target;
        this.transaction = transaction;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        if(method.getName().equals("save") || method.getName().equals("update")){
            this.transaction.beginTransaction();
            result = method.invoke(target,args);//调用目标类的目标方法
            this.transaction.commit();
        }else{
            result = method.invoke(target,args);//调用目标类的目标方法
        }

        return result;
    }
}
  • 优点:动态代理产生的对象,只需要一个拦截器就OK了。
  • 缺点:
    • 如果invoke方法中需要判断,将是一件非常复杂的事情。
    • 程序员需要写拦截器,写拦截器中的方法,所以invoke方法还需要修改  

2.2 CGLIB动态代理--基于类的动态代理

  • PersonDAO.java
package com.xuweiwei.dynamicproxy;

public class PersonDAO {

    public void save(){
        System.out.println("保存用户信息");
    }
}
  • MyInterceptor.java
package com.xuweiwei.dynamicproxy;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class MyInterceptor implements MethodInterceptor {
    private Object target ;
    private Transaction transaction;

    public MyInterceptor(Object target, Transaction transaction) {
        this.target = target;
        this.transaction = transaction;
    }

    public Object createProxy(){
        Enhancer enhancer = new Enhancer();
        enhancer.setCallback(this);//this表示拦截器对象
        enhancer.setSuperclass(target.getClass());//设置代理类的父类为目标类
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        this.transaction.beginTransaction();
        Object result = method.invoke(this.target,args);
        this.transaction.commit();
        return result;
    }
}
  • Transaction.java
package com.xuweiwei.dynamicproxy;
//事务
public class Transaction {

    public void beginTransaction(){
        System.out.println("开启事务");
    }

    public void commit(){
        System.out.println("提交");
    }

}
  • 测试
package com.xuweiwei.dynamicproxy;

import org.junit.Test;

public class TestDynamic {

    @Test
    public void test(){
        PersonDAO target = new PersonDAO();
        Transaction transaction = new Transaction();
        MyInterceptor interceptor = new MyInterceptor(target,transaction);
        PersonDAO proxy = (PersonDAO) interceptor.createProxy();
        proxy.save();

    }
}

3 AOP的术语

  • 以2.1中的代码为例

  • 织入:形成代理对象的方法的过程就是织入。
  • 【注意】

    • 通知就是切面中的方法
    • 代理对象的方法就是通知+目标方法
    • 连接点就是目标接口中的一个方法
    • 拦截器中的invoke方法就是代理对象的方法=通知+目标方法
    • 在现实的开发中,通知和目标方法完全是松耦合的  

4 XML方式的AOP

  • PersonDAO.java
package com.xuweiwei.aop;

public interface PersonDAO {
    public void savePerson();

}
  • PersonDAOImpl.java
package com.xuweiwei.aop;

public class PersonDAOImpl implements PersonDAO {
    @Override
    public void savePerson() {
        System.out.println("保存用户信息");
    }
}
  • Transaction.java
package com.xuweiwei.aop;
public class Transaction {

    public void beginTransaction(){
        System.out.println("开启事务");
    }

    public void commit(){
        System.out.println("提交");
    }

}
  • appliationContext.xml
<?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/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 id="personDAO" class="com.xuweiwei.aop.PersonDAOImpl"></bean>

    <!-- 切面 -->
    <bean id="transaction" class="com.xuweiwei.aop.Transaction"/>

    <!--
        配置AOP
    -->
    <aop:config>
        <!--
            配置切入点
        -->
        <aop:pointcut id="pointcut" expression="execution(* com.xuweiwei.aop.PersonDAOImpl.*(..))"/>
        <!--
            配置切面
        -->
        <aop:aspect ref="transaction">
            <!--
                前置通知
            -->
            <aop:before method="beginTransaction" pointcut-ref="pointcut"/>

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

        </aop:aspect>

    </aop:config>

</beans>
  • 测试
package com.xuweiwei.test;

import com.xuweiwei.aop.PersonDAO;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAOP {
    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        PersonDAO personDAO = (PersonDAO) context.getBean("personDAO");
        personDAO.savePerson();

    }
}

5 通知

  • 前置通知:在目标方法执行之前
   /**
     * 前置通知
     *  JoinPoint:连接点,客户端调用那个方法,这个方法就是连接点
     */
    public void beginTransaction(JoinPoint joinPoint){
        System.out.println("目标类"+joinPoint.getTarget().getClass());
        System.out.println("目标方法"+joinPoint.getSignature().getName());
        System.out.println("目标类"+joinPoint.getArgs().length);
        System.out.println("开启事务");
    }
<?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/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 id="personDAO" class="com.xuweiwei.aop.PersonDAOImpl"></bean>

    <!-- 切面 -->
    <bean id="transaction" class="com.xuweiwei.aop.Transaction"/>

    <!--
        配置AOP
    -->
    <aop:config>
        <!--
            配置切入点
        -->
        <aop:pointcut id="pointcut" expression="execution(* com.xuweiwei.aop.PersonDAOImpl.*(..))"/>
        <!--
            配置切面
        -->
        <aop:aspect ref="transaction">
            <!--
                前置通知
            -->
            <aop:before method="beginTransaction" pointcut-ref="pointcut"/>

        </aop:aspect>

    </aop:config>

</beans>
  • 后置通知,在目标方法执行之后(如果目标方法产生异常,后置通知不执行)
package com.xuweiwei.aop;

public interface PersonDAO {
    public String savePerson();

}
package com.xuweiwei.aop;

public class PersonDAOImpl implements PersonDAO {
    @Override
    public String savePerson() {
        System.out.println("保存用户信息");
        return "aa";
    }
}
package com.xuweiwei.aop;

import org.aspectj.lang.JoinPoint;

public class Transaction {

    /**
     * 后置通知
     * @param joinPoint
     * @param val
     */
    public void commit(JoinPoint joinPoint,Object val){
        System.out.println("目标方法的返回值:"+val);
        System.out.println("提交");
    }

}
<?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/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 id="personDAO" class="com.xuweiwei.aop.PersonDAOImpl"></bean>

    <!-- 切面 -->
    <bean id="transaction" class="com.xuweiwei.aop.Transaction"/>

    <!--
        配置AOP
    -->
    <aop:config>
        <!--
            配置切入点
        -->
        <aop:pointcut id="pointcut" expression="execution(* com.xuweiwei.aop.PersonDAOImpl.*(..))"/>
        <!--
            配置切面
        -->
        <aop:aspect ref="transaction">
            <!--
                后置通知
            -->
            <aop:after-returning method="commit" pointcut-ref="pointcut" returning="val"/>

        </aop:aspect>

    </aop:config>

</beans>
  • 异常通知:当发生异常的时候,此通知执行
package com.xuweiwei.aop;

public interface PersonDAO {
    public String savePerson();

}
package com.xuweiwei.aop;

public class PersonDAOImpl implements PersonDAO {
    @Override
    public String savePerson() {
        System.out.println("保存用户信息");

        int a = 1/0;

        return "aa";
    }
}
package com.xuweiwei.aop;

import org.aspectj.lang.JoinPoint;

public class Transaction {

    public void throwingMethod(JoinPoint joinPoint,Throwable ex){
        System.out.println("发生异常:"+ex.getMessage());
        System.out.println("异常通知");
    }

}
<?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/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 id="personDAO" class="com.xuweiwei.aop.PersonDAOImpl"></bean>

    <!-- 切面 -->
    <bean id="transaction" class="com.xuweiwei.aop.Transaction"/>

    <!--
        配置AOP
    -->
    <aop:config>
        <!--
            配置切入点
        -->
        <aop:pointcut id="pointcut" expression="execution(* com.xuweiwei.aop.PersonDAOImpl.*(..))"/>
        <!--
            配置切面
        -->
        <aop:aspect ref="transaction">
            <!--
                异常通知
            -->
            <aop:after-throwing method="throwingMethod" pointcut-ref="pointcut" throwing="ex"/>

        </aop:aspect>

    </aop:config>

</beans>
  • 最终通知:不管目标方法发生什么,都要执行此通知
package com.xuweiwei.aop;

public class Transaction {

    public void finallyMethod(){
        System.out.println("最终通知");
    }

}
<?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/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 id="personDAO" class="com.xuweiwei.aop.PersonDAOImpl"></bean>

    <!-- 切面 -->
    <bean id="transaction" class="com.xuweiwei.aop.Transaction"/>

    <!--
        配置AOP
    -->
    <aop:config>
        <!--
            配置切入点
        -->
        <aop:pointcut id="pointcut" expression="execution(* com.xuweiwei.aop.PersonDAOImpl.*(..))"/>
        <!--
            配置切面
        -->
        <aop:aspect ref="transaction">
            <!--
                最终通知
            -->
            <aop:after method="finallyMethod" pointcut-ref="pointcut" />

        </aop:aspect>

    </aop:config>

</beans>
  • 环绕通知:在目标方法执行前后,此通知执行
package com.xuweiwei.aop;

import org.aspectj.lang.ProceedingJoinPoint;

public class Transaction {

    public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知执行前");
        joinPoint.proceed();
        System.out.println("环绕通知执行后");
    }

}
<?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/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 id="personDAO" class="com.xuweiwei.aop.PersonDAOImpl"></bean>

    <!-- 切面 -->
    <bean id="transaction" class="com.xuweiwei.aop.Transaction"/>

    <!--
        配置AOP
    -->
    <aop:config>
        <!--
            配置切入点
        -->
        <aop:pointcut id="pointcut" expression="execution(* com.xuweiwei.aop.PersonDAOImpl.*(..))"/>
        <!--
            配置切面
        -->
        <aop:aspect ref="transaction">
            <!--
                环绕通知
            -->
            <aop:around method="aroundMethod" pointcut-ref="pointcut" />

        </aop:aspect>

    </aop:config>

</beans>
  • 示例:一个切入点跟多个切面
package com.xuweiwei;
public interface PersonDao {

    public void savePerson();

}
package com.xuweiwei;

/**
 * 目标类
 */
public class PersonDaoImpl implements PersonDao {

    @Override
    public void savePerson() {
        System.out.println("保存用户信息");
    }
}
package com.xuweiwei;

/**
 * 切面
 */
public class Logger {
    /**
     * 通知
     */
    public void logging(){
        System.out.println("打印日志");
    }
}
package com.xuweiwei;
/**
 * 切面
 */
public class Transaction {
    /**
     * 通知
     */
    public void beginTransaction(){
        System.out.println("开启事务");
    }
    /**
     * 通知
     */
    public void commit(){
        System.out.println("提交事务");
    }

}
<?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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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
       http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

      <!--
            目标类
      -->
      <bean id="personDao" class="com.xuweiwei.PersonDaoImpl"></bean>

      <!--
            切面
       -->
      <bean id="transaction" class="com.xuweiwei.Transaction"></bean>
      <!--
             切面
        -->
      <bean id="logger" class="com.xuweiwei.Logger"></bean>

      <!--  -->
      <aop:config>
            <aop:pointcut id="pointcut" expression="execution(* com.xuweiwei.PersonDaoImpl.*(..) )"/>
            <aop:aspect ref="logger">
                  <aop:before method="logging" pointcut-ref="pointcut"/>
            </aop:aspect>
            <aop:aspect ref="transaction">
                  <aop:before method="beginTransaction" pointcut-ref="pointcut"/>
                  <aop:after method="commit" pointcut-ref="pointcut" />
            </aop:aspect>
      </aop:config>

</beans>
package com.xuweiwei;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    @org.junit.Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        PersonDao personDao = (PersonDao) context.getBean("personDao");
        personDao.savePerson();

    }

}

6 xml方式的AOP的案例---使用Spring AOP进行异常处理(对所有的service进行异常处理)

  • dao层

    • PersonDAO.java  
package com.xuweiwei.exception.dao;

public interface PersonDAO {

    public void savePerson() throws Exception;

}
    • PersonDAOImpl.java  
package com.xuweiwei.exception.dao.impl;

import com.xuweiwei.exception.dao.PersonDAO;

public class PersonDAOImpl implements PersonDAO{

    @Override
    public void savePerson() throws Exception {
       int a = 1/ 0;
    }
}
  • service层

    • PersonService.java  
package com.xuweiwei.exception.service;

public interface PersonService {

    public void savePerson() throws Exception;

}
    • PersonServiceImpl.java  
package com.xuweiwei.exception.service.impl;

import com.xuweiwei.exception.dao.PersonDAO;
import com.xuweiwei.exception.service.PersonService;

public class PersonServiceImpl implements PersonService {

    private PersonDAO personDAO;

    public PersonDAO getPersonDAO() {
        return personDAO;
    }

    public void setPersonDAO(PersonDAO personDAO) {
        this.personDAO = personDAO;
    }

    @Override
    public void savePerson() throws Exception {
        personDAO.savePerson();
    }
}
  • action

    • PersonAction.java  
package com.xuweiwei.exception.action;

import com.xuweiwei.exception.service.PersonService;

public class PersonAction  {
    private PersonService personService;

    public PersonService getPersonService() {
        return personService;
    }

    public void setPersonService(PersonService personService) {
        this.personService = personService;
    }

    public void savePerson(){

        try {
            this.personService.savePerson();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

}
  • aspect(异常切面)

    • ExceptionAspect.java  
package com.xuweiwei.exception.aspect;

import org.aspectj.lang.JoinPoint;

import javax.servlet.http.HttpServletResponse;

//异常的切面
public class ExceptionAspect {

    //处理异常的通知
    public void hanleException(JoinPoint joinPoint, Throwable ex){
        printLog(ex);

    }

    private void printLog(Throwable ex) {

    }

}
  • applicationContext.xml
<?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/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">

    <!-- dao -->
    <bean id="personDAO" class="com.xuweiwei.exception.dao.impl.PersonDAOImpl"/>

    <!-- service -->
    <bean id="personService" class="com.xuweiwei.exception.service.impl.PersonServiceImpl">
        <property name="personDAO" ref="personDAO"/>
    </bean>

    <bean id="personAction" class="com.xuweiwei.exception.action.PersonAction">
        <property name="personService" ref="personService"/>
    </bean>

    <!-- 切面 -->
    <bean id="aspect" class="com.xuweiwei.exception.aspect.ExceptionAspect"></bean>

    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.xuweiwei.exception.service.*.*(..))"/>
        <aop:aspect ref="aspect">
            <aop:after-throwing method="hanleException" throwing="ex" pointcut-ref="pointcut"/>
        </aop:aspect>

    </aop:config>

</beans>
  • 测试
package com.test;

import com.xuweiwei.exception.action.PersonAction;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestException {

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        PersonAction personAction = (PersonAction) context.getBean("personAction");
        personAction.savePerson();

    }

}

7 注解方式的AOP

  • 步骤:

    • ①在applicationContext.xml中设置如下信息  
<?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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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
       http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

     <context:component-scan base-package="com.xuweiwei"/> 

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

</beans>
    • ②在切面类中设置@Component和@Aspect,以及切入点,请看下面  
package com.xuweiwei;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 切面
 */
@Component
@Aspect //此注解表明这是一个切面
public class Transaction {

    //设置切入点
    @Pointcut("execution( * com.xuweiwei.PersonDaoImpl.*(..))")
    private void pointcut(){}

    /**
     * 设置前置通知
     */
    @Before("pointcut()")
    public void beginTransaction(){
        System.out.println("开启事务");
    }
    /**
     * 设置最终通知
     */
    @After("pointcut()")
    public void commit(){
        System.out.println("提交事务");
    }

}
package com.xuweiwei;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 切面
 */
@Component
@Aspect
public class Logger {

    //设置切入点
    @Pointcut("execution(* com.xuweiwei.PersonDaoImpl.*(..))")
    private void pointcut(){}

    /**
     * 设置前置通知
     */
    @After("pointcut()")
    public void logging(){
        System.out.println("打印日志");
    }
}
    • 目标类实现的接口和目标类  
package com.xuweiwei;
public interface PersonDao {

    public void savePerson();

}
package com.xuweiwei;

import org.springframework.stereotype.Component;

/**
 * 目标类
 */
@Component("personDao")
public class PersonDaoImpl implements PersonDao {

    @Override
    public void savePerson() {
        System.out.println("保存用户信息");
    }
}
    • 测试    
package com.xuweiwei;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    @org.junit.Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        PersonDao personDao = (PersonDao) context.getBean("personDao");
        personDao.savePerson();

    }

}

Spring 4.x (二)的更多相关文章

  1. spring boot / cloud (二) 规范响应格式以及统一异常处理

    spring boot / cloud (二) 规范响应格式以及统一异常处理 前言 为什么规范响应格式? 我认为,采用预先约定好的数据格式,将返回数据(无论是正常的还是异常的)规范起来,有助于提高团队 ...

  2. Spring Data(二)查询

    Spring Data(二)查询 接着上一篇,我们继续讲解Spring Data查询的策略. 查询的生成 查询的构建机制对于Spring Data的基础是非常有用的.构建的机制将截断前缀find-By ...

  3. spring boot / cloud (二十) 相同服务,发布不同版本,支撑并行的业务需求

    spring boot / cloud (二十) 相同服务,发布不同版本,支撑并行的业务需求 有半年多没有更新了,按照常规剧本,应该会说项目很忙,工作很忙,没空更新,吧啦吧啦,相关的话吧, 但是细想想 ...

  4. Spring IOC(二)容器初始化

    本系列目录: Spring IOC(一)概览 Spring IOC(二)容器初始化 Spring IOC(三)依赖注入 Spring IOC(四)总结 目录 一.ApplicationContext接 ...

  5. 深入理解Spring AOP之二代理对象生成

    深入理解Spring AOP之二代理对象生成 spring代理对象 上一篇博客中讲到了Spring的一些基本概念和初步讲了实现方法,当中提到了动态代理技术,包含JDK动态代理技术和Cglib动态代理 ...

  6. spring AOP 之二:@AspectJ注解的3种配置

    @AspectJ相关文章 <spring AOP 之二:@AspectJ注解的3种配置> <spring AOP 之三:使用@AspectJ定义切入点> <spring ...

  7. Spring Boot 2 (二):Spring Boot 2 动态 Banner

    Spring Boot 2 (二):Spring Boot 2 动态 Banner Spring Boot 2.0 提供了很多新特性,其中就有一个小彩蛋:动态 Banner. 一.配置依赖 使用 Sp ...

  8. Spring Boot(十二):spring boot如何测试打包部署

    Spring Boot(十二):spring boot如何测试打包部署 一.开发阶段 1,单元测试 在开发阶段的时候最重要的是单元测试了,springboot对单元测试的支持已经很完善了. (1)在p ...

  9. (转)Spring Cloud(二)

    (二期)23.微服务框架spring cloud(二) [课程23]熔断器-Hystrix.xmind0.1MB [课程23]微服务...zuul.xmind0.2MB 熔断器-Hystrix 雪崩效 ...

  10. spring cloud: zuul(二): zuul的serviceId/service-id配置(微网关)

    spring cloud: zuul(二): zuul的serviceId/service-id配置(微网关) zuul: routes: #路由配置表示 myroute1: #路由名一 path: ...

随机推荐

  1. java字符串比较

    我最近刚学java,今天编程的时候就遇到一个棘手的问题,就是关于判断两个字符串是否相等的问题.在编程中,通常比较两个字符串是否相同的表达式是"==",但在java中不能这么写.在j ...

  2. 成功破解邻居的Wifi密码

    // 这是一篇导入进来的旧博客,可能有时效性问题. 默认配置的路由器,8位以下密码,黑客几分钟就可以破解.以前用自己的路由器做过实验,这次真正实践成功.环境:Kali Linux工具集:aircrac ...

  3. CCNA笔记(2)

    CCNA第一天笔记:何为因特网?答:因特网,是连接各台pc与终端设备,正是因为有了因特网,我们才能与全世界交流,玩在线游戏,在线学习.因特网给我们教育带来什么方便?答:没有了地域的阻止,可以在线学习, ...

  4. LibreOJ NOI Round #1 Day 1 B. 失控的未来交通工具

    瞬间移动 官方题解 题意:一个带边权无向图,加边以及询问在 x,x+b,...,x+(c−1)bx,x+b,...,x+(c-1)bx,x+b,...,x+(c−1)b 这些数中,有多少存在一条与之模 ...

  5. hihoCoder #1094 : Lost in the City(枚举,微软苏州校招笔试 12月27日 )

    #1094 : Lost in the City 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Little Hi gets lost in the city. He ...

  6. [hdu3943]K-th Nya Number

    挺正常的一道模板题. f[i][j][k]表示i位的数,有j个4,k个7的方案数. 具体实现的话...我写了发二分答案..需要注意的是二分时应该是mid=L+(R-L)/2..不然分分钟爆longlo ...

  7. POJ3041-Asteroids-匈牙利算法

    Asteroids Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 23963   Accepted: 12989 Descr ...

  8. hihoCoder1498-Diligent Robots

    #1498 : Diligent Robots Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB Description The ...

  9. 并查集-HDU1232-畅通工程

    转的其他人的.不知道谁的. 来看一个实例,杭电1232畅通工程 首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的.最后要解决的是整幅图的连通性问题.比如随意 ...

  10. BZOJ1786: [Ahoi2008]Pair 配对/1831: [AHOI2008]逆序对

    这两道题是一样的. 可以发现,-1变成的数是单调不降. 记录下原有的逆序对个数. 预处理出每个点取每个值所产生的逆序对个数,然后dp转移. #include<cstring> #inclu ...