1、AOP 概述
AOP概述
AOP为Aspect Oriented Programming的缩写。意为面向切面编程。通过预编译方式和老实巴交行期动态代理实现程序
功能的统一维护的一种技术。AOP是OOP的延续、AOP:面向切面编程。AOP是OOP的扩展和延伸,解决OOP开发遇到问题。
AOP作用
在不修改源代码的情况下、可以实现功能的增强
传统代码是纵向体系代码复用、
AOP是横向抽取机制、基于代理思想、对原来目标对象、创建代理对象、在不修改原对象代码情况下、通过对代理对象、
调用增强功能的代码、从而对原有业务方法进行增强
AOP应用场景
场景一:记录日志
场景二:监控方法运行时间
场景三:权限抑制
场景四:缓存优化(第一调用查询数据库、将查询结果放入内存对象、第二次调用、直接从内存对象返回、不需要查询数据库)
场景五:事务管理(调用方法前开启事务、调用方法后提交关闭事务)
AOP原理
Spring中AOP有二种实现方式:
(1)、JDK动态代理 、只能对实现了接口的类产生代理。
(2)、Cglib动态代理、(类似于Javassist第三方代理技术):对没有实现接口的类产生代理对象。生成子类对象
2、Spring的AOP底层实现
(1)、JDK动态代理
UserDao.java接口
package com.day03.dao;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 21:48 2018/11/11
*/
public interface UserDao {
public abstract void save();
public abstract void delete();
public abstract void update();
public abstract void select();
}
//UserDaoImpl.java实现类
package com.day03.dao.Impl;
import com.day03.dao.UserDao;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 21:48 2018/11/11
*/
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("save方法。。。。。。。。。。。");
}
@Override
public void delete() {
System.out.println("delete方法。。。。。。。。。。。");
}
@Override
public void update() {
System.out.println("update......................");
}
@Override
public void select() {
System.out.println("select...........................");
}
}
代理类:TestProxy.java
package com.day03.test;
import com.day03.dao.UserDao;
import org.junit.Test;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy;
import java.lang.reflect.Method;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 11:47 2018/11/11
*/
public class TestProxy implements InvocationHandler {
private UserDao userDao;
public TestProxy(UserDao userDao) {
this.userDao = userDao;
}
@Test
public UserDao createProxy(){
UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(),this);
return proxy;
}
//回调方法
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
if ("save".equals(method.getName())){
//增强
System.out.println("增强权限。。。。。");
return method.invoke(userDao,objects);
}
return method.invoke(userDao,objects);
}
}
testDemo.java测试类
package com.day03.test;
import com.day03.dao.Impl.UserDaoImpl;
import com.day03.dao.UserDao;
import org.junit.Test;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 21:51 2018/11/11
*/
public class TestDemo {
@Test
public void test1() {
UserDao userDao = new UserDaoImpl();
UserDao proxy = new TestProxy(userDao).createProxy();
proxy.save();
//userDao.save();
proxy.delete();
proxy.update();
proxy.select();
}
}
(2)、Cglib动态代理
UserDao.java接口
package com.day03.dao;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 21:48 2018/11/11
*/
public interface UserDao {
public abstract void save();
public abstract void delete();
public abstract void update();
public abstract void select();
}
//
UserDaoImpl.java实现类
package com.day03.dao.Impl;
import com.day03.dao.UserDao;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 21:48 2018/11/11
*/
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("save方法。。。。。。。。。。。");
}
@Override
public void delete() {
System.out.println("delete方法。。。。。。。。。。。");
}
@Override
public void update() {
System.out.println("update......................");
}
@Override
public void select() {
System.out.println("select...........................");
}
}
//
CglibProxy.java动态代理
package com.day03.test;
import com.day03.dao.UserDao;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 14:57 2018/11/12
*/
public class CglibProxy implements MethodInterceptor {
private UserDao userDao;
public CglibProxy(UserDao userDao) {
this.userDao = userDao;
}
public UserDao createProxy(){
//1、创建cglib的核心类对象
Enhancer enhancer = new Enhancer();
//2、设置父类
enhancer.setSuperclass(userDao.getClass());
//3、设置回调(类似InvocationHandler对象)
enhancer.setCallback(this);
//4、创建代理对象
UserDao proxy = (UserDao) enhancer.create();
return proxy;
}
@Override
public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//判断方法是否为save;
if ("save".equals(method.getName())){
//增强
System.out.println("权限核验。。。。。。。。。。。");
return methodProxy.invokeSuper(proxy,objects);
}
return methodProxy.invokeSuper(proxy,objects);
}
}
//
TestDemo.java测试类
package com.day03.test;
import com.day03.dao.Impl.UserDaoImpl;
import com.day03.dao.UserDao;
import org.junit.Test;
/**
* @ Author :ShaoWei Sun.
* @ Date :Created in 21:51 2018/11/11
*/
public class TestDemo {
@Test
public void test1() {
UserDao userDao = new UserDaoImpl();
UserDao proxy = new CglibProxy(userDao).createProxy();
proxy.save();
//userDao.save();
proxy.delete();
proxy.update();
proxy.select();
}
}
3、AOP相关术语
Joinpoint (连接点)
连接点是指那些被拦截到的点、在spring中、这些点指的是方法、spring只支持方法类型的连接点
Pointcut(切入点)
指的是我们要对哪些Joinpoint进行拦截
Advice(通知/增强)
通知是指拦截到Joinpoint之后所要做的事情就是通知、通知分为前置通知、后置通知、异常通知、最终通知、环绕通知(切面要完成的功能)
Introduction(引介)
引介是一种特殊的通知、在不修改代码的前提下、Introduction可以在运行期为类动态地添加一些方法或Field
Target(目标对象)
代理的目标对象
Weaving(织入)
是指把增强应用到目标对象来创建新的代理对象的过程、spring采用动态代理织入、而Asp
Proxy(代理)
一个类被AOP织入增强后、就产生一个结果代理类
Aspect(切面)
是切入红开和通知(引介)的结合