Aop(Aspect-Oriented Programming),即面向切面编程。
Aspect:封装用于横向插入的系统功能(如:事务、日志等)类
Joinpoint:在程序执行过程中的某个阶段点
Pointcut:切面与程序流程的交叉点,即那些需要处理的连接点
Advice(通知/增强处理):在切点出所要执行的代码
Target Object(目标对象):指所有被通知/增强的对象
Proxy(代理):将通知应用到目标对象后,被动态创建的对象
Weaving(织入):将切面代码插入到目表对象上,从而生成代理对象的过程
JDK动态代理(对接口代理):
第一步:创建UserDao接口
package com.itheima.jdk;
/**
* 第一步:创建UserDao接口
*/
public interface UserDao {
/*
* 在接口中定义两个方法
*/
public void addUser();
public void deleteUser();
}
第二步:创建接口实现类,UserDaoImpl
package com.itheima.jdk;
public class UserDaoImpl implements UserDao {
@Override
public void addUser() {
System.out.println("addUser添加用户...");
}
@Override
public void deleteUser() {
System.out.println("deleteUser删除用户...");
}
}
第三步:定义切面MyAspect
package com.itheima.aspect;
public class MyAspect {
public void check_Permissions() {
System.out.println("模拟检查权限...");
}
public void log() {
System.out.println("模拟记录日志...");
}
}
第四步:创建代理类JdkProxy
package com.itheima.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.itheima.aspect.MyAspect;
/**
* JDK代理类
*/
//创建代理类需要继承InvocationHandler
public class JdkProxy implements InvocationHandler {
//第一步:声名目标类接口
private UserDao userDao;
//第二步:创建代理方法
public Object createProxy( UserDao userDao) {
this.userDao=userDao;
//1、类加载器
ClassLoader classLoader = JdkProxy.class.getClassLoader();
//2、被代理对象实现的所有接口
//将所有接口传给clazz
Class<?>[] clazz = userDao.getClass().getInterfaces();
//3、使用代理类,进行增强,返回的是代理后的对象
//return返回,进入invoke
return Proxy.newProxyInstance(classLoader, clazz, this);
}
/*
*所有动态代理类的方法调用,都会交由invoke()方法去处理
*proxy被代理后的对象
*method将要被执行的方法信息(反射)
*args执行方法时需要的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1、声明切面
MyAspect myAspect = new MyAspect();
//2、调用切面的方法,前增强
myAspect.check_Permissions();
//3、在目标类上调用方法,并传入参数
//调用目标类UserDaoImpl的addUser()方法
Object obj= method.invoke(userDao, args);
//后增强
myAspect.log();
return obj;
}
}
第五步:创建测试类
package com.itheima.jdk;
public class JdkTest {
public static void main(String[] args) {
//创建代理对象
JdkProxy jdkProxy = new JdkProxy();
//创建目标对象
UserDao userDao = new UserDaoImpl();
//从代理对象中获取增强后的目标对象
UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao);
//执行方法
//执行方法进入JdkProxy(代理)类
userDao1.addUser();
userDao1.deleteUser();
}
}
CGLIB代理(对类代理,不需定义接口):
第一步:创建UserDao类,定义addUser(){....}、deleteUser(){...}方法
package com.ithema.cglib;
public class UserDao {
public void addUser() {
System.out.println("添加用户...");
}
public void deleteUser() {
System.out.println("删除用户...");
}
}
第二步:创建MyAspect切面类
package com.ithema.aspect;
/**
* 切面类
*/
public class MyAspect {
public void check_Permissions() {
System.out.println("前增强....check_Permissions");
}
public void log() {
System.out.println("后增强....记录日志log");
}
}
第三步:创建CglibProxy代理类
package com.ithema.cglib;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import com.ithema.aspect.MyAspect;
/*
* CglibProxy代理类
*/
//使用jdk动态代理需要则需要继承InvocationHandler
//创建CglibProxy代理类,需要继承spring包中的,MethodInterceptor接口
public class CglibProxy implements MethodInterceptor {
/*
* jdk代理第一步:声明目标类接口private UserDao userDao;
* 第二步:创建代理方法
* 在代理方法中,需要将外部传入的userDao赋值给this.userDao
* 然后:
* 1、创建类加载器ClassLoader classLoader = JdkProxy.class.getClassLoader();
* 2、被代理对象实现接口Class<?>[] clazz = userDao.getClass().getInterfaces();
* 3、使用代理类,返回代理后对象return Proxy.newProxyInstance(classLoader, clazz, this);
*/
//cglib第一步:创建代理方法
public Object createProxy(Object target) {
//创建一个动态类对象
Enhancer enhancer = new Enhancer();
/*
* 确定需要增强的类,设置其父类
*/
enhancer.setSuperclass(target.getClass());
//添加回调函数
enhancer.setCallback(this);
//返回创建的代理类
return enhancer.create();
}
/**
* proxy Cglib根据指定父类生成的代理对象
* method拦截的方法
* args拦截方法的参数数组
* methodProxy方法的代理对象,用于执行父类的方法
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//创建切面类对象
MyAspect myAspect = new MyAspect();
//前增强
myAspect.check_Permissions();
//目标方法执行
Object obj = methodProxy.invokeSuper(proxy, args);
//后增强
myAspect.log();
return obj;
}
}
第四步:创建测试类
package com.ithema.cglib;
public class CglibTest {
public static void main(String[] args) {
//1、创建代理对象
CglibProxy cglibProxy = new CglibProxy();
//2、创建目标对象
UserDao userDao = new UserDao();
//3、获取增强后的目标对象
UserDao userDao2 = (UserDao) cglibProxy.createProxy(userDao);
//4、执行方法
userDao2.addUser();
userDao2.deleteUser();
}
}