AOP和IOC是Spring的两大思想,AOP即面向切面编程,和OOP相辅相成,具体请看: AOP(面向切面编程)
这里学习一下它的底层实现方法----动态代理,动态代理关键的是代理,就像你去公司办事,你有什么需求,不可能直接找到 boss(源代码),而是通过秘书(代理)来实现你的需求,Boss办事也是通过代理实现的,(java中很多的思想就是解耦和,将源代码和业务实现分开,尽量不要去动源代码,方便代码复用和管理)
1、JDK动态代理: 只能对实现了接口的类(或者直接对这个接口)进行代理
这一点很重要,如果JDK要对一个类进行动态代理,那么这个类必须是实现了一个接口,比如UserDaoImpl implement UserDao,这个时候才能对UserDaoImpl或者直接对UserDao进行代理
具体代理方法如下:
package cn.nupt.demo01.UserDao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//创建代理类
public class ProxyTest implements InvocationHandler {
private UserDao userDao;
// 构造函数,传入我要代理的类,初始化代理类
public ProxyTest(UserDao userDaoTrue) {
this.userDao = userDaoTrue;
}
// 创建代理类的实例:userDao.getClass().getInterfaces()就是获得这个接口实现的所有接口
public UserDao createProxy() {
// 返回的是Object,强转到接口或实现类
// 参数1:类加载器; 参数2:所有实现的接口集合;参数三:实现了InvocationHandler的类,在这里就是本身
UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(), this);
return userDaoProxy;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("save".equals(method.getName())) {
// 需要增强的方法
System.out.println("加入动态代理实现");
// 通过反射返回这个方法的实现
return method.invoke(userDao, args);
}
return method.invoke(userDao, args);
}
}
创建测试类:
@Test
public void test04() {
UserDao daoImpl = new UserDaoImpl();
UserDao proxy = new ProxyTest(daoImpl).createProxy();
proxy.save();
proxy.delete();
}
输出:
保存用户
加入动态代理实现
删除用户
2、Cglib动态代理: 可以直接对类代理
Cglib是第三方类库,需要导包,这里只需要将Spring的核心包导入就行了(见前面Spring配置)
具体代理方法如下:
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class ProxyDemo implements MethodInterceptor {
private Coustomer coustomer;
public ProxyDemo(Coustomer coustomer) {
this.coustomer = coustomer;
}
public Coustomer createProxy() {
// 1、创建cglib的核心类对象
Enhancer enhancer = new Enhancer();
// 2、设置父类
enhancer.setSuperclass(coustomer.getClass());
// 3、设置回调(相当于InvocationHandler)
enhancer.setCallback(this);
// 4、创建代理对象并返回
Coustomer proxy = (Coustomer) enhancer.create();
return proxy;
}
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if ("hehe".equals(method.getName())) {
System.out.println("增强了");
return methodProxy.invokeSuper(proxy, args);
}
return methodProxy.invokeSuper(proxy, args);
}
}
测试类:
@Test
public void test() {
Coustomer coustomer = new Coustomer();
Coustomer proxy = new ProxyDemo(coustomer).createProxy();
proxy.haha();
proxy.hehe();
}
输出:
haha
增强了
hehe