AOP增强

AOP联盟为通知Advice定义了org.aopalliance.aop.Interface.Advice

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

1、前置通知org.springframework.aop.MethodBeforeAdvice

	在目标方法执行前实施增强

2、后置通知org.springframework.aop.AfterReturningAdvice

	在目标方法执行后实施增强

3、环绕通知org.aopalliance.intercept.MethodInterceptor

	在目标方法执行前后实施增强

4、异常抛出通知org.springframework.aop.ThrowsAdvice

	在方法抛出异常后实施增强

通过案例来讲解

有接口的案例

  • BeforeAdvice类
public class BeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("前置增强==================");
    }
}
  • StudentDao 类
public interface StudentDao {
    public void demo1();
    public void demo2();
}

  • StudentDaoImpl 类
public class StudentDaoImpl implements StudentDao {
    @Override
    public void demo1() {
        System.out.println("查询...");
    }
    @Override
    public void demo2() {
        System.out.println("保存...");
    }
 
}

  • 创建一个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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--配置目标类======================-->
    <bean id="studentDao" class="com.aop.demo.StudentDaoImpl"></bean>

    <!--前置通知类型=================-->
    <bean id="myBeforeAdvice" class="com.aop.demo.BeforeAdvice"></bean>

    <!--Spring的aop产生代理对象-->
    <bean id="studentDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--配置的目标类-->
        <property name="target" ref="studentDao"></property>
        <!--实现的接口-->
        <property name="proxyInterfaces" value="com.aop.demo.StudentDao"></property>
        <!--采用拦截的名称-->
        <property name="interceptorNames" value="myBeforeAdvice"></property>
        <property name="optimize" value="true"></property>
    </bean>
</beans>
  • 测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:ApplicationContext.xml")
public class SpringDemo {

    @Resource(name="studentDaoProxy")
    private StudentDao studentDao;
    
    @Test
    public void demo(){
        studentDao.demo1();
        studentDao.demo2();
    }
}

使用环绕通知

无接口案例

  • CustomerDao 类
public class CustomerDao {
 public void demo1() {
        System.out.println("查询...");
    }
    public void demo2() {
        System.out.println("保存...");
    }
}
  • AroundAdvice 类
public class AroundAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("环绕前=======");
        /*invocation.proceed()用来执行目标方法*/
        Object obj=invocation.proceed();
        System.out.println("环绕后===========");
        return obj;
    }
}
  • AplicationContext配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="customerDao" class="com.aop.demo.CustomerDao"></bean>
    <!--配置通知-->
    <bean id="AroudAdive" class="com.aop.demo.AroundAdvice"></bean>
    <!--一般的切面使用通知作为切面的,因为要对目标类的某个方法进行增强就需要配置一个带有切入点的切面-->
    <bean id="Advisor1" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!--pattern中配置正则表单时:.任意字符,*任意次数-->
        <property name="pattern" value=".*"></property>
        <property name="advice" ref="AroudAdive"></property>
        
    </bean>
    <!--配产生代理-->
    <bean id="customerDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--配置目标-->
        <property name="tar9get" ref="customerDao"></property>
        <property name="proxyTargetClass" value="true"></property>
        <property name="interceptorNames" value="Advisor1"></property>
    </bean>
</beans>
  • 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:ApplicationContext.xml")
public class SpringDemo {
     @Resource(name="customerDaoProxy")
    private CustomerDao customerDao;

    @Test
    public void demo1(){
        customerDao.demo1();
        customerDao.demo2();
      
    }
}

BeanNameAutoProxyCreator自动创建代理案例(基于Bean名称的自动代理,根据目标类的名称产生代理)

  • CustomerDao 类
public class CustomerDao {
 public void demo1() {
        System.out.println("查询...");
    }
    public void demo2() {
        System.out.println("保存...");
    }
}
  • StudentDao 类
public interface StudentDao {
 public void demo1() ;
     
 public void demo2() ;
     
}
  • StudentDaoImpl
public class StudentDaoImpl implements StudentDao {
   public void demo1() {
        System.out.println("查询...");
    }
    public void demo2() {
        System.out.println("保存...");
    }
}
  • AroundAdvice 类
public class AroundAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("环绕前=======");
        /*invocation.proceed()用来执行目标方法*/
        Object obj=invocation.proceed();
        System.out.println("环绕后===========");
        return obj;
    }
}
  • BeforeAdvice类
public class BeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("前置增强==================");
    }
}
  • AplicationContext配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--配置目标类-->
    <bean id="studentDao" class="com.aop.demo.StudentDaoImpl"></bean>
    <bean id="customerDao" class="com.aop.demo.CustomerDao"></bean>

    <!--配置增强-->
    <bean id="BeforeAdvice" class="com.aop.demo.BeforeAdvice"></bean>
    <bean id="AroundAdvice" class="com.aop.demo.AroundAdvice"></bean>

    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames" value="*Dao"></property>
        <!-- value=""可以更改成AroundAdvice||BeforeAdvice,使用其中一种增强-->
        <property name="interceptorNames" value="BeforeAdvice"></property>
    </bean>
</beans>
</beans>
  • 测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:ApplicationContext.xml")
public class SpringDemo {

   @Resource(name = "studentDao")
   private StudentDao studentDao;

   @Resource(name = "customerDao")
   private CustomerDao customerDao;
    @Test
    public void demo(){
        studentDao.demo1();;
        studentDao.demo2();
        customerDao.demo1();
        customerDao.demo2();
    }
}

DefaultAdvisorAutoProxyCreator自动创建代理案例(基于切面信息自动代理或者说根据Advisor本身包含信息创建代理)

上述代码完全不变

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--配置目标类-->
    <bean id="studentDao" class="com.aop.demo.StudentDaoImpl"></bean>
    <bean id="customerDao" class="com.aop.demo.CustomerDao"></bean>

    <!--配置增强-->
    <bean id="myBeforeAdvice" class="com.aop.demo.MyBeforeAdvice"></bean>
    <bean id="myAroundAdvice" class="com.aop.demo.MyAroundAdvice"></bean>

   <!--配置切面-->
    <bean id="myAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    	<!--value="添加方法"-->
        <property name="patterns" value="com\.aop\.demo\.CustomerDao\.demo1,com\.aop\.demo\.StudenDao\.demo2"></property>
        <property name="advice" ref="myAroundAdvice"></property>
    </bean>
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
</beans>

以上便是AOP增强的讲解,讲的不都清楚的,或者将错的,欢迎在评论区评论

发布了24 篇原创文章 · 获赞 5 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44519467/article/details/103740623