Spring一般切面
2019-02-14 本文已影响0人
往事随风_0817
Spring一般切面
Spring 实现了AOP联盟Advice这个接口=>org.aopalliance.aop.Interface.Advice
Spring 按照通知Advice在目标类方法的连接点位置,可以分为5类
- 前置通知 org.springframework.aop.MethodBeforeAdvice=>在目标方法执行前实施增强
- 后置通知 org.springframework.aop.AfterReturningAdvice=>在目标方法执行后实施增强
- 环绕通知 org.aopalliance.intercept.MethodInterceptor=>在目标方法执行前后实施增强
- 异常抛出通知 org.springframework.aop.ThrowsAdvice=>在方法抛出异常后实施增强
- 引介通知(了解) org.springframework.aop.IntroductionInterceptor=>在目标类中添加一些新的方法和属性
Spring是不支持引介通知---知道有这个通知就可以了
AOP切面类型
- Advisor:代表一般切面,Advisor本身就是一个切面,对目标类所有方法进行拦截
- PointcutAdvisor:代表具有切点的切面,可以指定拦截目标类哪些方法
- IntroductionAdvisor:代表引介切面,针对引介通知而使用切面(了解就行)
Advisor切面一些配置说明
- Spring中是通过ProxyFactoryBean来完成对目标类的增强
-
参数
- target:代理的目标对象
- proxyInterfaces:代理要实现的接口
如果多个接口可以使用以下格式赋值<list> <value></value> ...... </list>
- proxyTargetClass:是否对类代理=>而不是接口,设置为true时,使用CGLib代理
- interceptorNames:需要织入目标的Advisor
- singleton:返回代理是否为单例,默认单例
- optimize:当设置true时,强制使用CgLib
Advisor切面Demo
//这是一个Dao的实现类
public class StudentDaoImpl implements StudentDao {
public void find() {System.out.println("学生查询...");}
public void save() {System.out.println("学生保存...");}
public void update() {System.out.println("学生修改...");}
public void delete() {System.out.println("学生删除...");}
}
//配置Advice通知方式
public class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
//增强代码
System.out.println("权限验证...");
}
}
//Spring-XML配置
<!--配置目标类-->
<bean id="studentDao" class="cn.akwangl.advisor.StudentDaoImpl"/>
<!--前置通知类型-->
<bean id="myBeforeAdvice" class="cn.akwangl.advisor.MyBeforeAdvice"/>
<!--Spring的AOP 产生代理对象-->
<bean id="studentDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--配置目标类-->
<property name="target" ref="studentDao"/>
<!--实现的接口-->
<property name="proxyInterfaces" value="cn.akwangl.advisor.StudentDao"/>
<!--采用拦截的名称-->
<property name="interceptorNames" value="myBeforeAdvice"/>
</bean>
//Test类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class MyBeforeAdvice_Test {
@Resource(name = "studentDaoProxy")
private StudentDao studentDao;
@Test
public void demo1() {
studentDao.save();
studentDao.update();
studentDao.delete();
studentDao.find();
}
}
JDK是通过接口来完成横向切面,CgLib是通过纵向切面来完成目标类的增强
PointcutAdvisor切点切面Demo
//这里并没有使用横向切面方式,而是使用纵向切面
public class CustomerDao {
public void find(){System.out.println("查询客户...");}
public void save(){System.out.println("保存客户...");}
public void update(){System.out.println("修改客户...");}
public void delete(){System.out.println("删除客户...");}
}
//配置Advice通知方式
public class MyAroundAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("权限验证...");
Object proceed = methodInvocation.proceed();
System.out.println("日志记录...");
return proceed;
}
}
//Spring-XML配置
<!--增强目标-->
<bean id="customerDao" class="cn.akwangl.pointcutadvisor.CustomerDao"/>
<!--通知-->
<bean id="myAroundAdvice" class="cn.akwangl.pointcutadvisor.MyAroundAdvice"/>
<!--配置拦截的方法-->
<bean id="myAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!--要拦截的连接点-->
<property name="patterns" value=".*save*,.*update*"/>
<property name="advice" ref="myAroundAdvice"/>
</bean>
<!-- 配置产生代理 -->
<bean id="customerDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--配置增强目标-->
<property name="target" ref="customerDao"/>
<!--将它设置成纵向切面-->
<property name="proxyTargetClass" value="true"/>
<!--配置通知名称-->
<property name="interceptorNames" value="myAdvisor"/>
</bean>
//Test类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class SpringDemo4 {
@Resource(name = "customerDaoProxy")
private CustomerDao customerDao;
@Test
public void demo1(){
customerDao.find();
customerDao.save();
customerDao.update();
customerDao.delete();
}
}