1、AOP的概念
A、连接点(JoinPoint)
业务代码与服务器连接的位置
B、通知(Advice)
通知是连接点(JoinPoint)的具体行为,有几种通知:
1)置前通知
2)置后通知
3)环绕通知
C、切入点(PointCut)
横切关注点(服务代码)织入到哪些类中
D、切面(Aspect)
横切关注点的实现叫切面
切面 = 切入点 + 通知
——前面的类B就是切面
E、目标对象(Target)
业务对象
——前面的类A就是目标对象
在代码实现中,我们只要定义一个切面(Aspect)就可以了。
首先,我们定义一个切面类(HelloAspect):
public class HelloAspect {
public void beforeService(){
System.out.println("日志开始了");
}
public void afterService(){
System.out.println("日志结束了");
}
public void aroundService(ProceedingJoinPoint pjp){
System.out.println("日志开始时间"+new Date());
try {
pjp.proceed(); //执行业务方法
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("日志结束时间"+ new Date());
}
}
再定义一个业务类(HelloService):
public class HelloService {
public void hello1(){
System.out.println("我是类的业务方法1。。。");
}
public void hello2(){
System.out.println("我是类的业务方法2");
}
public void hello3(){
System.out.println("我是类的业务方法3");
}
}
通过Schema来实现AOP
<bean id="HServie" class="cn.gson.springmavenTest.aspect.HelloService"></bean>
<bean id="HAspect" class="cn.gson.springmavenTest.aspect.HelloAspect"></bean>
<aop:config>
<aop:aspect ref="HAspect">
<aop:before method="beforeService"
pointcut="execution(* cn.gson.springmavenTest.aspect.HelloService.hello1(..))" />
<aop:after method="afterService"
pointcut="execution(* cn.gson.springmavenTest.aspect.HelloService.hello2(..))"/>
<aop:around method="aroundService"
pointcut="execution(* cn.gson.springmavenTest.aspect.HelloService.hello3(..))"/>
</aop:aspect>
</aop:config>
测试:
ApplicationContext ac =
new ClassPathXmlApplicationContext("appaicationContext.xml");
HelloService hs = ac.getBean(HelloService.class);
hs.hello1();
hs.hello2();
hs.hello3();
运行结果:
日志开始了
我是类的业务方法1。。。
我是类的业务方法2
日志结束了
日志开始时间Tue Jun 13 09:35:14 CST 2017
我是类的业务方法3
日志结束时间Tue Jun 13 09:35:14 CST 2017
零配置的方式:
/**
* 切面类
*/
@Component
@Aspect
public class HelloAspect {
@Before(value="execution(* cn.gson.springmavenTest.aspect.HelloService.hello1(..))")
public void beforeService(){
System.out.println("日志开始了");
}
@After(value="execution(* cn.gson.springmavenTest.aspect.HelloService.hello2(..))")
public void afterService(){
System.out.println("日志结束了");
}
@Around(value="execution(* cn.gson.springmavenTest.aspect.HelloService.hello3(..))")
public void aroundService(ProceedingJoinPoint pjp){
System.out.println("日志开始时间"+new Date());
try {
pjp.proceed(); //执行业务方法
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("日志结束时间"+ new Date());
}
}
xml中开启注解
<!-- 启用AOP的注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<bean id="HServie" class="cn.gson.springmavenTest.aspect.HelloService"></bean>
<bean id="HAspect" class="cn.gson.springmavenTest.aspect.HelloAspect"></bean>
注意:
execution表达式
execution表达式是切入点(PointCut)中使用的一种模式,比如
execution(* com.sample.service.impl...(..))
第一个号:表示返回类型,号表示所有的类型。
包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。
第二个号:表示类名,号表示所有的类。
(..):最后这个星号表示方法名,号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。