Spring AOP的实现方式是动态织入,动态织入的方式是在运行时动态将要增强的代码织入到目标类中,这样往往是通过动态代理技术完成的;如Java JDK的动态代理(Proxy,底层通过反射实现)或者CGLIB的动态代理(底层通过继承实现),Spring AOP采用的就是基于运行时增强的代理技术。
接口使用JDK代理
结构如下:
![](https://i-blog.csdnimg.cn/blog_migrate/48a7751c67d0435fe67f6463a8e9ffa3.png)
APP
public static void main(String[] args) {
// create and configure beans
/* ApplicationContext context = new ClassPathXmlApplicationContext("aspects.xml");*/
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
"com.pooj.framework");
// retrieve configured instance
IJdkProxyService service = context.getBean(IJdkProxyService.class); //这里要写接口
// use configured instance
service.doMethod1();
service.doMethod2();
try {
service.doMethod3();
} catch (Exception e) {
// e.printStackTrace();
}
}
}
定义接口
public interface IJdkProxyService {
void doMethod1();
String doMethod2();
String doMethod3() throws Exception;
}
实现接口:
@Service
public class JdkProxyDemoServiceImpl implements IJdkProxyService {
@Override
public void doMethod1() {
System.out.println("JdkProxyServiceImpl.doMethod1()");
}
@Override
public String doMethod2() {
System.out.println("JdkProxyServiceImpl.doMethod2()");
return "hello world";
}
@Override
public String doMethod3() throws Exception {
System.out.println("JdkProxyServiceImpl.doMethod3()");
throw new Exception("some exception");
}
}
定义切面
@EnableAspectJAutoProxy
@Component
@Aspect
public class LogAspect1 {
/**
* define point cut.
*/
@Pointcut("execution(* com.pooj.framework.service.*.*(..))")
private void pointCutMethod() {
}
/**
* 环绕通知.
*
* @param pjp pjp
* @return obj
* @throws Throwable exception
*/
@Around("pointCutMethod()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("-----------------------");
System.out.println("环绕通知: 进入方法");
Object o = pjp.proceed();
System.out.println("环绕通知: 退出方法");
return o;
}
/**
* 前置通知.
*/
@Before("pointCutMethod()")
public void doBefore() {
System.out.println("前置通知");
}
/**
* 后置通知.
*
* @param result return val
*/
@AfterReturning(pointcut = "pointCutMethod()", returning = "result")
public void doAfterReturning(String result) {
System.out.println("后置通知, 返回值: " + result);
}
/**
* 异常通知.
*
* @param e exception
*/
@AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
public void doAfterThrowing(Exception e) {
System.out.println("异常通知, 异常: " + e.getMessage());
}
/**
* 最终通知.
*/
@After("pointCutMethod()")
public void doAfter() {
System.out.println("最终通知");
}
}
输出:
![](https://i-blog.csdnimg.cn/blog_migrate/dc98b2423f80aaad6630efb72618544b.png)
非接口使用Cglib代理
CglibProxyDemoServiceImpl
public class CglibProxyDemoServiceImpl {
public void doMethod1() {
System.out.println("CglibProxyDemoServiceImpl.doMethod1()");
}
public String doMethod2() {
System.out.println("CglibProxyDemoServiceImpl.doMethod2()");
return "hello world";
}
public String doMethod3() throws Exception {
System.out.println("CglibProxyDemoServiceImpl.doMethod3()");
throw new Exception("some exception");
}
}
切面定义:不变
app
public static void main(String[] args) {
// create and configure beans
/* ApplicationContext context = new ClassPathXmlApplicationContext("aspects.xml");*/
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
"com.pooj.framework");
// retrieve configured instance
CglibProxyDemoServiceImpl service = context.getBean(CglibProxyDemoServiceImpl.class); //这里改为非接口service
// use configured instance
service.doMethod1();
service.doMethod2();
try {
service.doMethod3();
} catch (Exception e) {
// e.printStackTrace();
}
}
}
输出
![](https://i-blog.csdnimg.cn/blog_migrate/62088cb9a00e661eec8bfa8b411c8861.png)