Spring IOC AOP (二)
2015-06-17 20:35
489 查看
spring AOP(Aspect Oriented Programming面向切面编程)和ioc是spring两大核心。面试时也会有很多面试官提问这些问题。通过一些例子加深对aop的印象。
在理解aop的基础上,首先应该明白什么是动态代理和反射。因为Spring框架里面大量的使用了动态代理和反射机制。这是我根据别人的相关代码总结的反射和动态代理
()Spring 实现动态代理配置有两种配置文件:1.xml文件方式,
2.annotation方式(使用Aspectj类库实现。)
spring 的相关概念:joinpoint:
Spring支持五种类型的通知:
Before(前) org.apringframework.aop.MethodBeforeAdvice
After-returning(返回后) org.springframework.aop.AfterReturningAdvice
After-throwing(抛出后) org.springframework.aop.ThrowsAdvice
Arround(周围) org.aopaliance.intercept.MethodInterceptor
Introduction(引入) org.springframework.aop.IntroductionInterceptor
在下面的小例子中说明spring通过注解是如何实现代理的。
首先在配置文件添加关于aspectj这是专门用来实现代理的框架。
beans.xml配置:
如果你觉得上面@Before、@AfterReturning、@AfterThrowing这些通知后面每次都要加(“execution(public * com.neusoft.impl...(..))”)
太麻烦的话,也可以自己定义一个方法。使用形式如下:
@Pointcut(“execution(public * com.neusoft.service...(..))”) public
void Method(){}
@Before(“Method()”)
public void doBefore(){
System.out.println(“在add方法前执行*“);
}
XML配置形式。
到这里大致就把注解中spring aop的知识点总结了一遍,这时候如果我们的AopIpml在service层增加逻辑会不会结果也和在impl层一样呢?
实验得知控制台会报错,原因就是我们service层UserService 没有实现接口,实现借口后,就会使用jdk自带的 Proxy,InvocationHandler来帮助
你产生代理。如果没有实现接口,就会直接操作二进制码的类库(cglib)来实现代理。加入cglib架报即可。
在理解aop的基础上,首先应该明白什么是动态代理和反射。因为Spring框架里面大量的使用了动态代理和反射机制。这是我根据别人的相关代码总结的反射和动态代理
()Spring 实现动态代理配置有两种配置文件:1.xml文件方式,
2.annotation方式(使用Aspectj类库实现。)
spring 的相关概念:joinpoint:
Spring支持五种类型的通知:
Before(前) org.apringframework.aop.MethodBeforeAdvice
After-returning(返回后) org.springframework.aop.AfterReturningAdvice
After-throwing(抛出后) org.springframework.aop.ThrowsAdvice
Arround(周围) org.aopaliance.intercept.MethodInterceptor
Introduction(引入) org.springframework.aop.IntroductionInterceptor
在下面的小例子中说明spring通过注解是如何实现代理的。
首先在配置文件添加关于aspectj这是专门用来实现代理的框架。
beans.xml配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <context:annotation-config /> <context:component-scan base-package="com.neusoft"/> <aop:aspectj-autoproxy /> <!-- <bean id="userImpl" class="com.neusoft.impl.UserImpl"></bean> <bean id="userService" class="com.neusoft.service.UserService"> <property name="user"> <ref bean="userImpl"/> </property> </bean> --> </beans>
package com.neusoft.dao; public interface User { public String add(); } package com.neusoft.impl; import org.springframework.stereotype.Component; import com.neusoft.dao.User; @Component("userImpl") public class UserImpl implements User{ @Override public void add() { System.out.println("*****这里是add方法*******"); throw new RuntimeException("Exception!"); } } package com.neusoft.service; import javax.annotation.Resource; import org.springframework.stereotype.Component; import com.neusoft.dao.User; @Component("userService") public class UserService { private User user; public void addUser(){ user.add(); } @Resource(name="userImpl") public void setUser(User user) { this.user = user; } } package com.neusoft.aop; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; @Aspect @Controller /*这里spring2.5里Component、service、Repository等注解用处差不多。用来初始化AopExample 这个类,这样spring才能把AopExample 和add()关联起来。 */ public class AopExample { /* 我们要把doBefore()这个方法在add()方法之前执行; ("execution(public void add())")。 在service包或其子包中定义的任意方法的执行: execution(* com.xyz.service..*.*(..)) */ @Before(value="execution(public void com.neusoft.impl.UserImpl.add())") //@Before(value="execution(public * com.neusoft.impl..*.*(..))")和上面表达意思一致 /* 执行结果: @Before**在add方法前执行*** *****这里是add方法******* */ public void doBefore(){ System.out.println("**在add方法前执行***"); } @AfterReturning(value="execution(public * com.neusoft.impl..*.*(..))") /* 执行结果: *****这里是add方法******* @AfterReturning**在add方法后执行*** */ public void doAfter(){ System.out.println("@AfterReturning**在add方法后执行***"); } @AfterThrowing("execution(public * com.neusoft.impl..*.*(..))") //让UserImpl中抛个异常信息;在UserImpl自己定义一个异常。 /* 执行结果: *****这里是add方法******* @AfterThrowing**在add方法后执行*** */ public void afterThrowing(){ System.out.println("@AfterThrowing**在add方法后执行***"); } //环绕通知:在方法执行前后和抛出异常时执行,相当于综合了以上三种通知 @Around("execution(public * com.neusoft.impl..*.*(..))") /* 执行结果: @Around**在add方法前执行*** *****这里是add方法******* @AfterThrowing**在add方法后执行*** * */ public void around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("@Around**在add方法前执行***"); pjp.proceed(); System.out.println("@AfterThrowing**在add方法后执行***"); } }
如果你觉得上面@Before、@AfterReturning、@AfterThrowing这些通知后面每次都要加(“execution(public * com.neusoft.impl...(..))”)
太麻烦的话,也可以自己定义一个方法。使用形式如下:
@Pointcut(“execution(public * com.neusoft.service...(..))”) public
void Method(){}
@Before(“Method()”)
public void doBefore(){
System.out.println(“在add方法前执行*“);
}
XML配置形式。
<bean id="userImpl" class="com.neusoft.impl.UserImpl"></bean> <bean id="userService" class="com.neusoft.service.UserService"> <property name="user"> <ref bean="userImpl"/> </property> </bean> <bean id="aopExample" class="com.neusoft.aop.AopExample"></bean> <aop:config > <aop:aspect id="aspect" ref="aopExample"> <aop:pointcut expression="execution(public * com.neusoft.impl..*.*(..))" id="impl"/> <aop:before method="doBefore" pointcut-ref="impl"/> <aop:after-returning method="doAfter" pointcut-ref="impl"/> <aop:after-throwing method="afterThrowing" throwing="ex" pointcut-ref="impl"/> <aop:around method="around" pointcut-ref="impl"/> </aop:aspect> </aop:config>
到这里大致就把注解中spring aop的知识点总结了一遍,这时候如果我们的AopIpml在service层增加逻辑会不会结果也和在impl层一样呢?
实验得知控制台会报错,原因就是我们service层UserService 没有实现接口,实现借口后,就会使用jdk自带的 Proxy,InvocationHandler来帮助
你产生代理。如果没有实现接口,就会直接操作二进制码的类库(cglib)来实现代理。加入cglib架报即可。
相关文章推荐
- Spring IOC AOP详解(一)
- java try catch finally中的return问题
- 初识JAVA
- JDK中的Date类的小误区和获取自定义日期的号数和毫秒转日期
- 初学java之jdk安装,基本概念,简单代码编写
- 用代理更新eclipse SDK for android
- LeetCode155 MinStack java题解
- 疯狂Java学习笔记(87)-----------十篇必读的Java文章
- 初识JAVA2
- javaweb中乱码的问题
- java线程池使用
- 最新版springside4基于Quickstart项目,创建自己的项目
- Java知多少(95)绘图基础
- Struts2入门1
- java运行环境的配置
- angular的post请求,SpringMVC后台接收不到参数值的解决方案
- Spring4配置AOP
- Guava EventBus配合Spring完成事件分发可配置(变通使用三方库)
- JavaWeb_Servlet开发
- Java习惯用法总结