这里写自定义目录标题
Spring Aop
什么是Aop?
AOP:Aspect Oriented Programming,中文翻译为”面向切面编程“。面向切面编程是一种编程范式,它作为OOP面向对象编程的一种补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理、权限控制、缓存控制、日志打印等等。AOP采取横向抽取机制,取代了传统纵向继承体系的重复性代码。
aop的术语:
(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知
(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
Aop的作用
oop与aop的对比
-
oop:纵向抽取
好处:1)提高可重用性
2)提高可扩展和可维护
3)多态 -
aop:横向向抽取
好处:1)提高可重用性
2)提高可扩展和可维护
怎么使用Aop?
aop底层原理:动态代理技术 jdk动态代理和cglib动态代理
1)jdk动态代理: 只能入侵实现接口的对象。 针对接口实现类
jdk接口:InvocationHandler
2)spring动态代理:针对类(aspect包—spring提供的)
aopalliance: MethodInteceptor 当类实现接口内部用的jdk动态代理 如果类没有实现接口 使用cglib动态代理
jdk动态代理:
//通知
package com.jr.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.jr.dao.UserDao;
public class JdkHK implements InvocationHandler{
private Object target;
public JdkHK(UserDao userDao) {
this.target=userDao;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("启动");
//修改传进来的参数
args[0] = 89;
args[1] = 92;
//调用目标对象的方法
Object result = method.invoke(target, args);
System.out.println("结束");
return result;
}
}
//测试
package com.jr.proxy;
import java.lang.reflect.Proxy;
import com.jr.dao.UserDao;
import com.jr.dao.impl.UserDaoImpl;
public class Test01 {
public static void main(String[] args) {
//目标对象
UserDao target = new UserDaoImpl();
//jdk黑客对象
JdkHK jdkHK = new JdkHK(target);
//代理对象
UserDao userDao = (UserDao) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] {UserDao.class}, jdkHK);
int result = userDao.add(3, 4);
System.out.println("结果:"+result);
}
}
cglib动态代理
//通知
package com.jr.proxy;
import org.aopalliance.intercept.Invocation;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class SpringHk implements MethodInterceptor{
//目标对象
private Object target;
@Override
public Object invoke(MethodInvocation Invocation) throws Throwable {
可插入需要的操作//
Object result = Invocation.proceed();
return result;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
}
//bean工厂配置文件
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--1.目标对象 -->
<bean id="scoreDao" class="com.jr.dao.impl.ScoreDaoImpl"></bean>
<bean id="userDao" class="com.jr.dao.impl.userDaoImpl"></bean>
<!--2.spring 黑客对象 -->
<bean id="springHk" class="com.jr.proxy.SpringHk">
</bean>
<!-- <bean id="jdkHk" class="com.cc.proxy.JdkHk">
<constructor-arg name="target" ref="userDaoInter"></constructor-arg>
</bean> -->
<!--3.代理对象 -->
<bean id="scoreDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 3.1 目标对象 -->
<property name="target" ref="scoreDao"></property>
<!-- 3.2 spring 黑客对象 -->
<property name="interceptorNames">
<array>
<value>springHk</value>
</array>
</property>
</bean>
<!--3.代理对象 -->
<bean id="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 3.1 目标对象 -->
<property name="target" ref="userDao"></property>
<!-- 3.2 目标对象接口 -->
<property name="proxyInterfaces" ref="com.jr.dao.userDao"></property>
<!-- 3.3 spring 黑客对象 -->
<property name="interceptorNames">
<array>
<value>springHk</value>
</array>
</property>
</bean>
</beans>