代理模式:为其他对象提供一种代理以控制目标对象的访问,在某些情况下, 一个对象不适合或者不能直接引用另外一个对象,代理对象可以在这个客户类和目标对象中起到一个桥梁作用。
简单来说,代理对象的使用,是在不修改原有目标对象的基础上,增强原有目标对象的功能逻辑。
代理的实现有两种,静态代理和动态代理,而动态代理,又分为jdk动态代理和cglib动态代理。
本文目录:
- 1.静态代理的实现
- 2.jdk动态代理的实现
- 3.cglib动态代理的实现
1.静态代理
需要目标类实现接口,代理类和目标类实现相同的接口,静态代理,是有代理类的,而动态代理是没有的。
1.1定义接口类UserService
package com.java4all.test_proxy_static;
/**
* author:lightClouds917
* date:2018/10/7
* description:接口
*/
public interface UserService {
String doFirst();
void doSecond();
}
1.2定义接口类的实现类
也就是我们的目标类,我们需要增强的类
package com.java4all.test_proxy_static;
/**
* author:lightClouds917
* date:2018/10/7
* description:接口实现类 目标类,等待增强
*/
public class UserServiceImpl implements UserService{
@Override
public String doFirst() {
System.out.println("执行了doFirst()方法");
return "iloveyou";
}
@Override
public void doSecond() {
System.out.println("执行了doSecond()方法");
}
}
1.3定义目标类的代理类
要和目标类实现相同的接口,在此代理类的方法中进行增强
package com.java4all.test_proxy_static;
import org.springframework.stereotype.Service;
/**
* author:lightClouds917
* date:2018/10/7
* description:静态代理 有代理类
* 在代理类中增强目标类的方法
*/
@Service
public class UserServiceImplProxy implements UserService{
@Override
public String doFirst() {
//调用目标类的原始方法
UserServiceImpl userService = new UserServiceImpl();
String str = userService.doFirst();
//增强逻辑 这里以字母转换为例
str = str.toUpperCase();
return str;
}
@Override
public void doSecond() {
UserService userService = new UserServiceImpl();
userService.doSecond();
}
}
1.4测试
测试一下,原本目标类中有个方法是返回iloveyou,在代理类中,我们对此方法进行了增强,将字母转为了大写进行返回。
package com.java4all.test_proxy_static;
/**
* author:lightClouds917
* date:2018/10/7
* description:测试静态代理
*/
public class TestProxy {
public static void main(String[]args){
test1();
System.out.println("--------------");
test2();
}
/**
* 调用原有的目标对象来实现功能
*/
public static void test1(){
UserService userService = new UserServiceImpl();
System.out.println(userService.doFirst());
userService.doSecond();
}
/**
* 调用代理对象来实现功能
*/
public static void test2(){
UserService userServiceImplProxy = new UserServiceImplProxy();
System.out.println(userServiceImplProxy.doFirst());
userServiceImplProxy.doSecond();
}
}
测试结果如下:
执行了doFirst()方法
iloveyou
执行了doSecond()方法
--------------
执行了doFirst()方法
ILOVEYOU
执行了doSecond()方法
2.jdk动态代理
jdk动态代理的原理是,和目标类实现共同的接口,由Proxy.newProxyInstance生成一个代理对象,在代理对象调用方法时,在invoke方法中增强。
jdk动态代理,不需要代理类,他的实现必须是要求目标类实现了某个接口,然后代理对象和目标类实现了相同的接口。
2.1定义接口
package com.java4all.test_proxy_jdk;
/**
* author:lightClouds917
* date:2018/10/7
* description:接口
*/
public interface UserService {
String doFirst();
void doSecond();
}
2.2定义实现类
也就是需要增强的目标类
package com.java4all.test_proxy_jdk;
/**
* author:lightClouds917
* date:2018/10/7
* description:接口实现类 目标类,等待增强
*/
public class UserServiceImpl implements UserService {
@Override
public String doFirst() {
System.out.println("执行了doFirst()方法");
return "iloveyou";
}
@Override
public void doSecond() {
System.out.println("执行了doSecond()方法");
}
}
2.3测试jdk动态代理
package com.java4all.test_proxy_jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* author:lightClouds917
* date:2018/10/7
* description:jdk动态代理
* 没有代理类
* 由Proxy.newProxyInstance生成一个代理对象,在调用方法时,在invoke方法中增强
* 要求:目标类存在接口,目标类和代理对象要实现相同的接口
*/
public class TestProxy {
public static void main(String[]args){
test1();
}
public static void test1(){
//目标类对象
UserService target = new UserServiceImpl();
/**jdk动态代理,没有代理类,由Proxy.newProxyInstance生成一个代理对象*/
UserService userService = (UserService)Proxy.newProxyInstance(
target.getClass().getClassLoader(),//目标类的类加载器
target.getClass().getInterfaces(), //目标类实现的所有接口
new InvocationHandler() { //匿名内部类
//proxy:代理对象
//method:目标方法
//args:目标方法参数列表
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = method.invoke(target, args);
if(invoke != null){
return invoke.toString().toUpperCase();
}
return null;
}
});
System.out.println(userService.doFirst());
userService.doSecond();
}
}
结果:
执行了doFirst()方法
ILOVEYOU
执行了doSecond()方法
3.cglib动态代理
cglib动态代理的原理是,生成目标类的子类,在子类中进行增强,这个子类对象就是代理对象。
使用cglib代理时,要求目标类必须可以被继承,即没有用final修饰。
CGLIB(code generation Library)是一个开源项目,是一个强大的,高性能的,高质量的代码生成类库。他可以在运行期间拓展和增强java类,Spring用它来实现AOP编程。
3.1目标类UserService
不需要实现接口
package com.java4all.test_proxy_cglib;
/**
* author:lightClouds917
* date:2018/10/7
* description:目标类,没有实现接口,等待增强
*/
public class UserService {
public String doFirst() {
System.out.println("执行了doFirst()方法");
return "iloveyou";
}
public void doSecond() {
System.out.println("执行了doSecond()方法");
}
}
3.2代理工厂
用来生成目标类的代理对象,此类需要实现MethodInterceptor
package com.java4all.test_proxy_cglib;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* author:lightClouds917
* date:2018/10/7
* description:返回目标类的代理对象
* 需要实现MethodInterceptor
*/
public class MyCglib implements MethodInterceptor{
private UserService target;
public MyCglib(UserService target) {
this.target = target;
}
/**
* 返回目标类的代理对象
* @return
*/
public UserService MyCglibCreator(){
Enhancer enhancer = new Enhancer();
//指定父类,即目标类 cglib原理:子类增强父类
enhancer.setSuperclass(UserService.class);
//设置回调接口 当前类继承了MethodInterceptor,
//此接口public interface MethodInterceptor extends Callback
enhancer.setCallback(this);
//create创建cglib动态代理对象
return (UserService)enhancer.create();
}
//回调接口的方法 代理对象执行目标方法时,会触发该方法
@Override
public Object intercept(Object o,
Method method,
Object[] objects,
MethodProxy methodProxy) throws Throwable {
Object invoke = method.invoke(target, objects);
if(invoke != null){
return invoke.toString().toUpperCase();
}
return invoke;
}
}
3.3测试cglib动态代理
package com.java4all.test_proxy_cglib;
/**
* author:lightClouds917
* date:2018/10/7
* description:cglib动态代理
*/
public class TestProxy {
public static void main(String[]args){
test1();
}
public static void test1(){
UserService target = new UserService();
//调用工厂类获取代理对象
MyCglib myCglib = new MyCglib(target);
UserService userService = myCglib.MyCglibCreator();
System.out.println(userService.doFirst());
userService.doSecond();
}
}