AOP面向切面编程
导包:aop包和aspects
//测试类
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//JUnit4帮助开启的方法
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:com/neusoft/springaop/applicationContext.xml")
public class AopTest {
@Resource(name="serviceAbc")
private ServiceAbc serviceAbc;
@Test
public void demo1(){
serviceAbc.save(1);
serviceAbc.save();
serviceAbc.update();
serviceAbc.delete();
}
}
//切面类
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
//@Component("myAdvice")
@org.aspectj.lang.annotation.Aspect
public class Aspect {
//所有这样路径的都经过Pointcut切入点
@Pointcut("execution(* com.neusoft.springaop.*AbcImpl.*(..))")
public void pc(){}
// 前置通知
//指定该方法是前置通知,并制定切入点
@Before("Aspect.pc()") //类名.方法()
//前置通知方法的使用,比较麻烦每一个都需要写这句话,所以切入点的使用就来了
// @Before("execution(* com.neusoft.springaop.*AbcImpl.*(..))")
public void before(){
System.out.println("开启事务!!");
}
//后置通知
@AfterReturning("Aspect.pc()")
// @AfterReturning("execution(* com.neusoft.springaop.*AbcImpl.*(..))")
public void afterReturning(){
System.out.println("这是后置通知(如果出现异常不会调用)!!");
}
//环绕通知
// @Around("execution(* com.neusoft.springaop.*AbcImpl.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("开启事务环绕通知!!");
Object proceed = pjp.proceed();//调用目标方法
System.out.println("关闭事务环绕通知!!");
return proceed;
}
//异常通知
// @AfterThrowing("execution(* com.neusoft.springaop.*AbcImpl.*(..))")
public void afterException(){
System.out.println("出事啦!出现异常了!!");
}
//后置通知
// @After("execution(* com.neusoft.springaop.*AbcImpl.*(..))")
public void after(){
System.out.println("这是后置通知(出现异常也会调用)!!");
}
}
//ServiceAbc 类
public interface ServiceAbc {
public void save(int i);
public void save();
public void delete();
public void update();
}
//ServiceAbcImpl 类
import org.springframework.stereotype.Service;
@Service("serviceAbc")
//注解的方式写入bean
public class ServiceAbcImpl implements ServiceAbc {
/* (non-Javadoc)
* @see com.easy.service.ServiceAbc#save()
*/
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("save");
}
/* (non-Javadoc)
* @see com.easy.service.ServiceAbc#delete()
*/
@Override
public void delete() {
// TODO Auto-generated method stub
System.out.println("delete");
}
/* (non-Javadoc)
* @see com.easy.service.ServiceAbc#update()
*/
@Override
public void update() {
// TODO Auto-generated method stub
System.out.println("update");
}
/* (non-JavaDoc)
* @see com.easy.springaop.ServiceAbc#save(int)
*/
@Override
public void save(int i) {
// TODO Auto-generated method stub
System.out.println(i+"save");
// i=i/0;
}
}
//如果不想使用注解那么就在XML配置
//注解配置了 所以XNM都使用了注释来编写
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd ">
<context:component-scan base-package="com.neusoft.springaop"></context:component-scan>
<!-- 准备工作: 导入aop(约束)命名空间 -->
<!-- 1.配置目标对象 -->
<!-- <bean name="serviceAbc" class="com.neusoft.springaop.ServiceAbcImpl" ></bean> -->
<!-- 2.配置通知对象 -->
<bean name="myAdvice" class="com.neusoft.springaop.Aspect" ></bean>
<!-- 3.配置将通知织入目标对象 -->
<!-- <aop:config> --><!--
execution(表达式)
表达式:
[方法访问修饰符] 方法返回值 包名.类名.方法名(方法的参数)
public void com.neusoft.springaop.ServiceAbcImpl.save()
void com.neusoft.springaop.ServiceAbcImpl.save()
* com.neusoft.springaop.ServiceAbcImpl.save()
* com.neusoft.springaop.ServiceAbcImpl.*()
* com.neusoft.springaop.*AbcImpl.*(..)
* com.neusoft.springaop..*AbcImpl.*(..) -->
<!-- <aop:pointcut expression="execution(* com.easy.springaop.*AbcImpl.*(..))" id="pc"/> -->
<!-- Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.
Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.
Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
Target(目标对象):代理的目标对象
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程.(动词)
spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入
Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
Aspect(切面): 是切入点和通知(引介)的结合
-->
<!--Joinpoint * com.neusoft.springaop.ServiceAbcImpl.*(..) -->
<!-- pointcut <aop:pointcut expression="execution(* com.neusoft.springaop.ServiceAbcImpl.*(..))" id="pc"/>-->
<!-- Advice <aop:before method="before" pointcut-ref="pc" /> -->
<!-- com.neusoft.springaop.ServiceAbcImpl -->
<!-- -->
<!-- <aop:pointcut expression="execution(* com.neusoft.springaop.ServiceAbcImpl.*(..))" id="pc"/> -->
<!-- <aop:aspect ref="myAdvice" > -->
<!-- 指定名为before方法作为前置通知 -->
<!-- <aop:before method="before" pointcut-ref="pc" /> -->
<!-- 后置 -->
<!-- <aop:after-returning method="afterReturning" pointcut-ref="pc" /> -->
<!--
环绕通知-->
<!-- <aop:around method="around" pointcut-ref="pc" /> -->
<!-- 异常拦截通知 -->
<!-- <aop:after-throwing method="afterException" pointcut-ref="pc"/> -->
<!-- 后置 -->
<!-- <aop:after method="after" pointcut-ref="pc"/> -->
<!-- </aop:aspect> -->
<!-- </aop:config> --> <!-- -->
<!-- 3.开启使用注解完成织入 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>