Spring基础知识(6)-AOP2

一、Spring AOP

      AOP 开发规范 : AOP联盟为通知Advice定义了org.aopalliance.aop.Interface.Advice
      Spring AOP 实现 AOP联盟定义 规范 

1、传统Spring AOP 提供 五类 Advice 

      前置通知(代码增强) org.springframework.aop.MethodBeforeAdvice

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

      后置通知 org.springframework.aop.AfterReturningAdvice
      * 在目标方法执行后实施增强
      环绕通知 org.aopalliance.intercept.MethodInterceptor
      * 在目标方法执行前后实施增强
      异常抛出通知 org.springframework.aop.ThrowsAdvice
      * 在方法抛出异常后实施增强
      引介通知 org.springframework.aop.IntroductionInterceptor 
      * 在目标类中添加一些新的方法和属性

2、 Spring 的切面  Advisor

      Advisor 就是对PointCut 应用 Advice (通常所说Advisor 指只有一个Point 和 一个 Advice )

      类型:

      Advisor : 代表一般切面,Advice本身就是一个切面,对目标类所有方法进行拦截 (没有切点)
      PointcutAdvisor : 代表具有切点的切面,可以指定拦截目标类哪些方法
      IntroductionAdvisor : 代表引介切面,针对引介通知而使用切面

3、案例一(不带切点的切面) : 使用普通Advisor, 使用Advice作为一个切面 ,不定义切点,拦截目标类 所有方法 

      1) 导入jar包 

         导入 aop联盟的规范 : com.springsource.org.aopalliance-1.0.0.jar
         导入 spring aop实现 : spring-aop-3.2.0.RELEASE.jar

      2) 编写被代理 接口和实现类

package lsq.spring.aop.advisor;
/**
 * 客户管理接口
 *
 * @author lishanquan
 *
 */
public interface CustomerDao {
	public void add();
	
	public void search();
	
	public void update();
	
	public void delete();
}
package lsq.spring.aop.advisor;

public class CustomerDaoImpl implements CustomerDao{

	@Override
	public void add() {
		System.out.println("客户添加……");
	}

	@Override
	public void search() {
		System.out.println("客户查询……");
	}

	@Override
	public void update() {
		System.out.println("客户更新……");
	}

	@Override
	public void delete() {
		System.out.println("客户删除……");
	}
	
}
      3) 编写前置通知 (在目标方法前执行...)

package lsq.spring.aop.advisor;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;
/**
 * 自定义前置增强方法
 *
 * @author lishanquan
 *
 */
public class MyMethodBeforeAdvice implements MethodBeforeAdvice{

	@Override
	public void before(Method method, Object[] args, Object target)
			throws Throwable {
		System.out.println("前置增强~~~~~~~~~~~~~~~~~~");
	}

}
      4) 为目标对象创建 , 配置applicationContext.xml 

            使用ProxyFactoryBean 为目标对象创建代理,ProxyFactoryBean会根据属性设置自动选择这两种方式进行动态代理。


	<!-- 被代理对象 -->
	<bean id="customerDao" class="lsq.spring.aop.advisor.CustomerDaoImpl"></bean>
	
	<!-- 增强 -->
	<bean id="myBeforeAdvice" class="lsq.spring.aop.advisor.MyMethodBeforeAdvice"></bean>
	
	<!-- 创建代理 -->
	<bean id="customerDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
		<!-- 目标 -->
		<property name="target" ref="customerDao"></property>
		<!-- 针对接口代理 -->
		<property name="proxyInterfaces" value="lsq.spring.aop.advisor.CustomerDao"></property>
		<!-- 增强
			 interceptorNames 表示可以运用多个 Advice, 必须写value
		 -->
		<property name="interceptorNames" value="myBeforeAdvice"></property>
	</bean>
      5)测试

package lsq.spring.aop.advisor;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * 测试不带切点的切面
 *
 * @author lishanquan
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringTest {
	//对测试对象进行自动注入
	@Autowired
	@Qualifier("customerDaoProxy") //☆注意:这里一定要注入增强后的代理对象,不能注入原来的Bean
	private CustomerDao customerDao;
	
	@Test
	public void demo(){
		customerDao.add();
		customerDao.search();
		customerDao.update();
		customerDao.delete();
	}
}
      ☆注意:在编程时,应该使用 ProxyFactoryBean 创建后代理对象(CustomerDAOProxy ), 不要引入原来Bean (CustomerDAO)

4、案例二 (带有切点的切面): 定义单独切点切面,指定被代理对象 哪些方法 会被增强

      * JdkRegexpMethodPointcut 构造正则表达式切点
      * 使用正则表达式 切点切面 org.springframework.aop.support.RegexpMethodPointcutAdvisor

      1)创建被代理对象 (没有接口 的类 )

package lsq.spring.aop.pointcutadvisor;
/**
 * 订单操作类
 *
 * @author lishanquan
 *
 */
public class OrderDao {
	public void save(){
		System.out.println("添加订单……");
	}
	
	public void edit(){
		System.out.println("编辑订单……");
	}
	
	public void update(){
		System.out.println("修改订单……");
	}
	
	public void delete(){
		System.out.println("删除订单……");
	}
}
      2)  增强 (编写环绕通知)

package lsq.spring.aop.pointcutadvisor;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/**
 * 自定义环绕增强
 *
 * @author lishanquan
 *
 */
public class MyMethodInterceptor implements MethodInterceptor{

	@Override
	//进行增强方法,methodInvocation调用目标方法
	public Object invoke(MethodInvocation methodInvocation) throws Throwable {
		System.out.println("环绕增强 方法前增强……");
		Object result = methodInvocation.proceed();//目标方法执行
		System.out.println("环绕增强 方法后增强……");
		return result;
	}
}
      3) 通过配置 ProxyFactory 为目标对象创建代理 

package lsq.spring.aop.pointcutadvisor;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/**
 * 自定义环绕增强
 *
 * @author lishanquan
 *
 */
public class MyMethodInterceptor implements MethodInterceptor{

	@Override
	//进行增强方法,methodInvocation调用目标方法
	public Object invoke(MethodInvocation methodInvocation) throws Throwable {
		System.out.println("环绕增强 方法前增强……");
		Object result = methodInvocation.proceed();//目标方法执行
		System.out.println("环绕增强 方法后增强……");
		return result;
	}
}
      4)测试

package lsq.spring.aop.pointcutadvisor;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringTest {
	//自动注入测试对象
	@Autowired
	@Qualifier("orderDaoProxy")
	private OrderDao orderDao;
	
	@Test
	public void demo(){
		orderDao.save();
		orderDao.edit();
		orderDao.update();
		orderDao.delete();
	}
}
      ☆☆☆注意:

      正则表达式案例
      lsq\.spring\.aop\.pointcutadvisor\.OrderDao\.save.*   ---- 执行OrderDAO 的save方法 
      .*save.*  ----- 包含save方法 
      <property name="patterns" value=".*save.*,.*delete.*"></property> ---- 同时增强save和delete方法

5、 自动代理

      使用ProxyFactoryBean 创建代理,需要为每个Bean 都配置一次 ,非常麻烦 
      自动代理原理: 根据xml中配置advisor的规则,得知切面对哪个类的哪个方法进行代理 (切面中本身就包含 被代理对象信息) ,就不需要ProxyFactoryBean ,使用       BeanPostProcessor 完成自动代理 
   

      BeanNameAutoProxyCreator 根据Bean名称创建代理 
      DefaultAdvisorAutoProxyCreator 根据Advisor本身包含信息创建代理
      * AnnotationAwareAspectJAutoProxyCreator 基于Bean中的AspectJ 注解进行自动代理


1) BeanNameAutoProxyCreator

	<!-- 被代理对象 -->
	<bean id="customerDao" class="lsq.spring.aop.advisor.CustomerDaoImpl"></bean>
	<bean id="orderDao" class="lsq.spring.aop.pointcutadvisor.OrderDao"></bean>
	
	<!-- 增强 -->
	<bean id="myBeforeAdvice" class="lsq.spring.aop.advisor.MyMethodBeforeAdvice"></bean>
	<bean id="myMethodInterceptor" class="lsq.spring.aop.pointcutadvisor.MyMethodInterceptor"></bean>
	
	<!-- 第一种BeanName自动代理 -->	
	<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
		<!-- 对所有以Dao结尾的Bean进行代理 -->
		<property name="beanNames" value="*Dao"></property>
		<!-- 增强 -->
		<property name="interceptorNames" value="myMethodInterceptor"></property>
	</bean>
package lsq.spring.aop.autoproxy;

import lsq.spring.aop.advisor.CustomerDao;
import lsq.spring.aop.pointcutadvisor.OrderDao;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext2.xml")
public class SpringTest {
	@Autowired
	@Qualifier("customerDao")
	private CustomerDao customerDao;
	
	@Autowired
	@Qualifier("orderDao")
	private OrderDao orderDao;
	
	@Test
	public void demo(){
		customerDao.add();
		orderDao.save();
	}
}

      效果:


      *** 自动代理和ProxyFactoryBean 本质区别 : 
      ProxyFactoryBean, 先有被代理对象, 传递ProxyFactoryBean,创建代理 
      自动代理 , 在Bean构造过程中, 使用后处理Bean 创建代理,返回构造完成对象就是代理对象

2) DefaultAdvisorAutoProxyCreator

        基于切面信息进行代理

	<!-- 被代理对象 -->
	<bean id="customerDao" class="lsq.spring.aop.advisor.CustomerDaoImpl"></bean>
	<bean id="orderDao" class="lsq.spring.aop.pointcutadvisor.OrderDao"></bean>
	
	<!-- 增强 -->
	<bean id="myBeforeAdvice" class="lsq.spring.aop.advisor.MyMethodBeforeAdvice"></bean>
	<bean id="myMethodInterceptor" class="lsq.spring.aop.pointcutadvisor.MyMethodInterceptor"></bean>
	
	<!-- 切面 -->	
	<bean id="myAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<!-- 切点拦截信息 -->
		<property name="patterns" value="lsq\.spring\.aop\.pointcutadvisor\.OrderDao.save.*"></property>
		<!-- 增强 -->
		<property name="advice" ref="myBeforeAdvice"></property>
	</bean>
	
	<!-- 第二种 基于切面信息自动代理 -->
	<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
package lsq.spring.aop.autoproxy;

import lsq.spring.aop.pointcutadvisor.OrderDao;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext3.xml")
public class SpringTest2 {
	@Autowired
	@Qualifier("orderDao")
	private OrderDao orderDao;
	
	@Test
	public void demo(){
		orderDao.save();
		orderDao.delete();
	}
}
      效果:










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOP(面向切面编程)是 Spring 框架一个重要模块,它通过在应用程序运行期间动态地将代码织入到目标方法中,实现了横切关注点的统一处理。下面是一些基础的知识点关于 Spring AOP: 1. 切面(Aspect): 切面是一个模块化单元,它封装了一组通用的横切关注点,如日志记录、事务管理等。切面由切点(Pointcut)和通知(Advice)组成。 2. 切点(Pointcut): 切点定义了在应用程序中哪些方法或类应该被织入切面逻辑。它使用表达式或者通配符来匹配方法的执行,并决定哪些方法应该被拦截。 3. 通知(Advice): 通知定义了在切点处执行的逻辑,它是切面的实际处理逻辑。Spring AOP 提供了不同类型的通知,包括前置通知(Before)、后置通知(After)、返回通知(AfterReturning)、异常通知(AfterThrowing)和环绕通知(Around)。 4. 连接点(Joinpoint): 连接点是在应用程序执行期间能够被拦截的特定位置,比如方法调用、方法执行、异常抛出等。切点决定了哪些连接点会被拦截。 5. 引入(Introduction): 引入是一种特殊的通知,它允许向现有的类动态添加新的方法或接口。通过引入,可以将一些额外的行为添加到现有类中。 6. 织入(Weaving): 织入是将切面与目标对象的方法连接起来的过程。织入可以在编译时、类加载时或运行时进行。 7. AOP 代理: Spring AOP 通过 JDK 动态代理和 CGLIB 代理来实现织入。JDK 动态代理只能对实现了接口的类进行织入,而 CGLIB 代理可以对任意类进行织入。 8. XML 配置和注解配置: Spring AOP 可以通过 XML 配置文件或注解来配置切面、切点和通知。XML 配置方式相对灵活,注解配置方式更简洁。 以上是关于 Spring AOP 的一些基础知识点的介绍。希望能帮助你理解 Spring AOP 的基本概念和使用方式。如果你有更多问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值