静态代理
由程序创建或者特定工具生成的源代码,在程序运行前,代理类的.class文件已经生成
通过将目标类与代理类实现同一个接口,让代理类持有真实类对
象,然后在代理类方法中调用真实类方法,在调用真实类方法的前
后添加我们所需要的功能扩展代码来达到增强的目的,一句话,自己手写代理类就是静态代理。
public interface ClothFactory {
/**
* 生产衣服
*/
void produceCloth();
}
// 被代理类
public class NikeClothFactory implements ClothFactory{
@Override
public void produceCloth() {
System.out.println("Nike开始生产衣服");
}
}
public class ClothProxyFactory implements ClothFactory{
// 创建代理类对象
private ClothFactory clothFactory;
public ClothProxyFactory(ClothFactory clothFactory){
this.clothFactory = clothFactory;
}
/**
* 对被代理类的方法进行拦截处理
*/
@Override
public void produceCloth() {
System.out.println("服饰工厂开始准备");
// 被代理类方法执行
clothFactory.produceCloth();
System.out.println("服饰工厂准备结束");
}
}
public class StaticProxyTest {
public static void main(String[] args) {
// 被代理类
NikeClothFactory nikeClothFactory = new NikeClothFactory();
ClothProxyFactory clothProxyFactory = new ClothProxyFactory(nikeClothFactory);
clothProxyFactory.produceCloth();
}
}
动态代理
JDK动态代理,要求目标对象实现一个接口,但是有时候目标对象只是
一个单独的对象,并没有实现任何的接口,这个时候就可以用CGLib动
态代理
JDK动态代理使自带的,CGLib需要引入第三方包
CGLib动态代理,他是在内存中构建一个子类对象从而实现对目标对象
功能的扩展
CGLib动态代理基于继承来实现代理,所以无法对final类、private方法
和static方法实现代理
JDK动态代理
public interface Human {
void breath();
void eat(String food);
}
public class Student implements Human{
@Override
public void breath() {
System.out.println("呼吸最新鲜的空气");
}
@Override
public void eat(String food) {
System.out.println("学生应该吃:"+food);
}
}
public class JDKProxy implements InvocationHandler {
// 创建被代理类对象
private Object targetObj;
// 返回被代理对象
public Object newInstance(Object targetObj){
this.targetObj = targetObj;
return Proxy.newProxyInstance(targetObj.getClass().getClassLoader(), targetObj.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理开始----------调用方法"+method.getName());
Object result = method.invoke(targetObj,args);
System.out.println("动态代理结束----------调用方法"+method.getName());
return result;
}
}
public class JDKProxyTest {
public static void main(String[] args) {
// 创建被代理类
Student student = new Student();
// JDK动态代理类
JDKProxy jdkProxy = new JDKProxy();
Human human = (Human) jdkProxy.newInstance(student);
human.breath();
human.eat("有营养的食物");
}
}
CGLib动态代理
public interface Human {
void breath();
void eat(String food);
}
public class Student implements Human{
@Override
public void breath() {
System.out.println("呼吸最新鲜的空气");
}
@Override
public void eat(String food) {
System.out.println("学生应该吃:"+food);
}
}
public class CGLibProxy implements MethodInterceptor {
// 代理类
private Object targetObj;
public Object newInstance(Object targetObj){
this.targetObj = targetObj;
// 创建CGLib代理类
Enhancer enhancer = new Enhancer();
// 设置代理类的⽗类(⽬标类)
enhancer.setSuperclass(this.targetObj.getClass());
// 设置代理类的⽗类(⽬标类)
enhancer.setCallback(this);
// 创建子类(代理对象)
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("CGLib动态代理开启-------调用方法"+method.getName());
// 调用被代理类
Object result = methodProxy.invokeSuper(o,objects);
System.out.println("CGLib动态代理结束-------调用方法"+method.getName());
return result;
}
}
public class CGLibTest {
public static void main(String[] args) {
// 创建被代理类
Student student = new Student();
// 创建CGLib被代理类
CGLibProxy cgLibProxy = new CGLibProxy();
Student human = (Student) cgLibProxy.newInstance(student);
human.breath();
human.eat("有营养的食物");
}
}
Spring AOP 底层原理
aop 底层是采用动态代理机制实现的:接口+实现类
如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象。
没有实现接口的对象,就无法使用JDK Proxy去进行代理了,这时候Spring AOP会使用Cglib生成一个被代理对象的子类来作为代理。
就是由代理创建出一个和impl实现类平级的一个对象,但是这个对象不是一个真正的对象,只是一个代理对象,但它可以实现和impl相同的功能,这个就是aop的横向机制原理,这样就不需要修改源代码。