一AOP相关概念
Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.
Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.
Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
Target(目标对象):代理的目标对象
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程.
spring采用动态代理织入,而AspectJ采用编译期织入和类装在期织入
Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
Aspect(切面): 是切入点和通知(引介)的结合
二、 AOP 的底层实现
AOP 底层使用的代理技术 : JDK动态代理 和 CGlib的动态代理。
AOP 开发规范 : AOP联盟为通知Advice定义了org.aopalliance.aop.Interface.Advice。 Spring AOP 实现 AOP联盟定义 规范
传统Spring AOP 提供 五类 Advice
a 前置通知(代码增强) org.springframework.aop.MethodBeforeAdvice 在目标方法执行前实施增强
b 后置通知 org.springframework.aop.AfterReturningAdvice 在目标方法执行后实施增强
c 环绕通知org.aopalliance.intercept.MethodInterceptor 在目标方法执行前后实施增强
d 异常抛出通知 org.springframework.aop.ThrowsAdvice 在方法抛出异常后实施增强
e 引介通知 org.springframework.aop.IntroductionInterceptor 在目标类中添加一些新的方法和属性
2、 Spring 的切面 Advisor
Advisor 就是对PointCut 应用 Advice (通常所说Advisor 指只有一个Point 和 一个 Advice )
通过配置实现增强
采用jdk动态代理实现,有一个接口UserService,实现类 UserImpl, 不配置切点
UserService接口
package dflx;
public interface UserService {
public void add();
public void serach();
}
实现类 UserImpl
public class UserImpl implements UserService {
@Override
public void add() {
System.out.println(" add user");
}
@Override
public void serach() {
System.out.println("search user");
}
}
AOP的配置如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 不带切点和切面 -->
<!-- 被代理对象 -->
<bean id="user" class="dflx.UserImpl"></bean>
<!-- 增强 -->
<bean id="mybeforeadvice" class="dflx.MethodBeforeTest"></bean>
<bean id="userDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 目标 -->
<property name="target" ref="user"></property>
<!-- 针对接口代理 -->
<property name="proxyInterfaces" value="dflx.UserService"></property>
<property name="interceptorNames" value="mybeforeadvice"></property>
</bean>
</beans>
image.png
通过如下方法测试
@Test
public void test() {
ApplicationContext app=new ClassPathXmlApplicationContext("app.xml");
UserService user=(UserService) app.getBean("userDAOProxy");
user.add();
user.serach();
}
结果如下
前置增强-----------
add user
前置增强-----------
search user
image.png
采用Cglib的动态代理,有切点和切面。
有一个 OrderDAO类,Advice通知增强类MyMethodInterceptor
public class OrderDAO {
public void add() {
System.out.println(" 添加订单");
}
public void delete() {
System.out.println(" 删除订单");
}
public void search() {
System.out.println(" 查询订单");
}
}
Advice通知增强类
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation arg) throws Throwable {
System.out.println("环绕前增强");
Object resultObject=arg.proceed(); //目标方法执行
System.out.println("环绕后增强");
return resultObject;
}
}
AOP的配置如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 带有切点的切面 -->
<!-- 被代理的对象 -->
<bean id="orderDAO" class="day0916.OrderDAO"></bean>
<!-- 增强 -->
<bean id="mymethodinter" class="day0916.MyMethodInterceptor"></bean>
<!-- 定义切点切面 -->
<bean id="myadvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="pattern" value=".*"></property>
<property name="advice" ref="mymethodinter"></property>
</bean>
<!-- 创建代理 -->
<bean id="orderDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 目标 -->
<property name="target" ref="orderDAO"></property>
<!-- 针对类代理 -->
<property name="proxyTargetClass" value="true"></property>
<!-- 增强 -->
<property name="interceptorNames" value="myadvisor"></property>
</bean>
</beans>
测试类如下
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:app2.xml")
public class SpringTest {
@Autowired
@Qualifier("orderDAOProxy")
private OrderDAO orderDAO;
@Test
public void test() {
orderDAO.add();
orderDAO.search();
orderDAO.delete();
}
}
结果如下
环绕前增强
添加订单
环绕后增强
环绕前增强
查询订单
环绕后增强
环绕前增强
删除订单
环绕后增强
image.png
网友评论