spring中的AOP就是利用JDK的动态代理来生成对象的,该对象可以作为目标对象使用
可是sping 中的AOP代理可以有JDK动态代理,也有CGLIB代理。
JDK 动态代理
- 首先创建UserDao,编写两个方法-添加和删除
package com.java.jdk;
/**
* Created by IntelliJ IDEA.
*
* @version : 1.0
* @auther : Firewine
* @mail : 1451661318@qq.com
* @Program Name: <br>
* @Create : 2018-12-05-19:12
* @Description : <br/>
*/
public interface UserDao {
public void addUser();
public void deleteUser();
}
- 实现UserDao 的两个方法
package com.java.jdk;
/**
* Created by IntelliJ IDEA.
*
* @version : 1.0
* @auther : Firewine
* @mail : 1451661318@qq.com
* @Program Name: <br>
* @Create : 2018-12-05-19:13
* @Description : <br/>
*/
public class UserDaoImpl implements UserDao{
//是以这个类作为目标类,进行增强处理
@Override
public void addUser() {
System.out.println("添加用户");
}
@Override
public void deleteUser() {
System.out.println("删除用户");
}
}
- 模拟切面,加个两个权限和日志方法
package com.java.aspect;
/**
* Created by IntelliJ IDEA.
*
* @version : 1.0
* @auther : Firewine
* @mail : 1451661318@qq.com
* @Program Name: <br>
* @Create : 2018-12-05-19:15
* @Description : <br/>
*/
public class MyAspect {
//下面两个方法模拟切面
/**
* 模拟权限检查方法
*/
public void check_Permissions(){
System.out.println("权限检查");
}
/**
* 模拟日志方法
*/
public void log(){
System.out.println("记录日志");
}
}
- 实现JDK代理类,需要实现InvocationHandle
package com.java.proxy;
import com.java.aspect.MyAspect;
import com.java.jdk.UserDao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by IntelliJ IDEA.
*
* @version : 1.0
* @auther : Firewine
* @mail : 1451661318@qq.com
* @Program Name: <br>
* @Create : 2018-12-05-19:17
* @Description : <br/>
*/
public class JdkProxy implements InvocationHandler {
//声明目标类接口
private UserDao userDao;
//创建代理方法
public Object createProxy(UserDao userDao){
this.userDao = userDao;
//1. 类加载器
ClassLoader classLoader = JdkProxy.class.getClassLoader();
//2. 被代理对象实现的所有接口
Class[] classes = userDao.getClass().getInterfaces();
//3. 使用代理类,进行增强,返回的是代理后的对象
return Proxy.newProxyInstance(classLoader,classes,this::invoke);
}
/**
* 所有的动态代理类的方法调用,都会交由invoke方法去处理
* @param proxy 就是被代理后的对象
* @param method 是要执行的方法(反射)
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* 第一个参数 : 当前类的类加载器
* 第二个参数 : 是被代理对象实现的所有的接口
* 第三个参数 : 代表代理类JdkProxy的本身
*/
//声明切面
MyAspect myAspect = new MyAspect();
//前增强
myAspect.check_Permissions();
//在目标类上调用方法,传入参数
Object obj = method.invoke(userDao,args);
//后增强
myAspect.log();
return obj;
}
}
- 最后一个编写测试类
package com.java.test;
import com.java.jdk.UserDao;
import com.java.jdk.UserDaoImpl;
import com.java.proxy.JdkProxy;
/**
* Created by IntelliJ IDEA.
*
* @version : 1.0
* @auther : Firewine
* @mail : 1451661318@qq.com
* @Program Name: <br>
* @Create : 2018-12-05-19:25
* @Description : <br/>
*/
public class JdkTest {
public static void main(String[] args) {
//创建代理对象
JdkProxy jdkProxy = new JdkProxy()
//创建目标对象
UserDao userDao = new UserDaoImpl();
//从代理对象获取增强后的目标对象
UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao);
userDao1.addUser();
userDao1.deleteUser();
}
}
- 结果显示
CGLIB代理
CGLIB 是一个高性能开源的代码生成包,它采用非常底层的字节码结束,对指定的目标类生成一个子类,并对子类进行增强。
这个也已经被集成到spring的核心包中了
- 实现一个目标类
package com.cglib.jdk;
/**
* Created by IntelliJ IDEA.
*
* @version : 1.0
* @auther : Firewine
* @mail : 1451661318@qq.com
* @Program Name: <br>
* @Create : 2018-12-05-19:30
* @Description : <br/>
*/
public class UserDao {
public void addUser() {
System.out.println("添加用户");
}
public void deleteUser() {
System.out.println("删除用户");
}
}
- 创建代理类,需要实现MethodInterceptor接口,并实现接口的intercept方法
package com.cglib.proxy;
import com.java.aspect.MyAspect;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* Created by IntelliJ IDEA.
*
* @version : 1.0
* @auther : Firewine
* @mail : 1451661318@qq.com
* @Program Name: <br>
* @Create : 2018-12-05-19:36
* @Description : <br/>
*/
public class CglibProxy implements MethodInterceptor {
public Object CreateProxy(Object object){
//创建一个动态类对象
Enhancer enhancer = new Enhancer();
//确定需要增强的类,设置其父类
enhancer.setSuperclass(object.getClass());
//添加回调函数
enhancer.setCallback( this);
//返回创建的代理类
return enhancer.create();
}
/**
* proxy CGLIB 根据指定父类生成的代理对象
* method 拦截的方法
* args 拦截方法的参数数组
* methodProxy 方法的代理对象,用于执行父类的方法
* @param
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//创建切面类对象
MyAspect myAspect = new MyAspect();
myAspect.check_Permissions();
Object object = methodProxy.invokeSuper(methodProxy,objects);
myAspect.log();
return object;
}
}
- 创建测试类
package com.cglib.test;
import com.cglib.jdk.UserDao;
import com.cglib.proxy.CglibProxy;
/**
* Created by IntelliJ IDEA.
*
* @version : 1.0
* @auther : Firewine
* @mail : 1451661318@qq.com
* @Program Name: <br>
* @Create : 2018-12-05-19:49
* @Description : <br/>
*/
public class CglibTest {
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
UserDao userDao = new UserDao();
UserDao userDao1 = (UserDao) cglibProxy.CreateProxy(userDao);
userDao1.addUser();
userDao1.deleteUser();
}
}
- Enhancer 是CGLIB的核心类,然后调用该类的setSuperclass方法来确定目标对象,然后setCallback方法添加回调函数,
- 而且这两个代理的不同之处,就是JDK需要实现接口的但是只需要jdk。而CGLIB是不需要接口的,但是需要导入Spring的核心包。