java动态代理(JDK和CGLIB)笔记
动态代理:为一堆interface或类的实现提供统一的执行通道,从含义上就像局域网电脑通过代理上网一样,走统一的通道,代理控制通道,自然可以在通道里加上自定义实现,例如像AOP切面,日志等。
JDK的动态代理只能对接口实现,代理类需要实现InvocationHandler 接口。
一、接口
public interface UserService {
User addUser();
void editUser(User user);
int deleteUser(int userId);
}
//假设有这么一个User类
public class User {
private Integer userId;
private String userName;
private String password;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
'}';
}
}
二、接口的实现
public class UserServiceImpl implements UserService {
@Override
public User addUser() {
User user = new User();
user.setUserId(1);
user.setUserName("userTest");
user.setPassword("123456");
System.out.println("------> add user");
return user;
}
@Override
public void editUser(User user) {
System.out.println("------> edit user:" +user);
}
@Override
public int deleteUser(int userId) {
System.out.println("------> delete user:"+userId);
return 1;
}
}
三、JDK代理类实现InvocationHandler
public class ProxyHandler implements InvocationHandler {
//被代理对象
private Object proxied;
public ProxyHandler(Object proxied) {
this.proxied = proxied;
}
private void beforeInvoke(String msg)
{
System.out.println("-------> beforInvoke:"+msg);
}
private void afterInvoke(String msg)
{
System.out.println("-------> afterInvoke:"+msg);
}
private String convertArgs(Object[] args)
{
if(args==null || args.length==0)
{
return null;
}
StringBuilder sb= new StringBuilder();
for(Object object : args)
{
sb.append(object.toString());
}
return sb.toString();
}
//proxy是代理对象,可以想象成代理服务器
//proxied是被代理对象,可以想象成局域网里的PC
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforeInvoke("proxy name:"+proxy.getClass().getName());
beforeInvoke("proxied name:"+proxied.getClass().getName());
beforeInvoke( "args:"+convertArgs(args));
Object o = method.invoke(proxied,args);
afterInvoke("result:"+o);
return o;
}
}
四、使用,实现原理是反射
public class Main {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService proxyUserService = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class},
new ProxyHandler(userService)
);
User user = proxyUserService.addUser();
proxyUserService.editUser(user);
proxyUserService.deleteUser(user.getUserId());
}
}
五、结果:符合预期的输出
六、简化一下写法,代理类的生成方式
public class DynamicProxy implements InvocationHandler {
private Object proxied;
private void beforeInvoke(String msg)
{
System.out.println("-------> beforInvoke:"+msg);
}
private void afterInvoke(String msg)
{
System.out.println("-------> afterInvoke:"+msg);
}
private String convertArgs(Object[] args)
{
if(args==null || args.length==0)
{
return null;
}
StringBuilder sb= new StringBuilder();
for(Object object : args)
{
sb.append(object.toString());
}
return sb.toString();
}
//在这里就把代理对象创建出来
public Object getProxyObject(Object proxied) {
this.proxied = proxied;
return Proxy.newProxyInstance(
this.proxied.getClass().getClassLoader(),
this.proxied.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforeInvoke("proxy name:"+proxy.getClass().getName());
beforeInvoke("proxied name:"+proxied.getClass().getName());
beforeInvoke( "args:"+convertArgs(args));
Object o = method.invoke(proxied,args);
afterInvoke("result:"+o);
return o;
}
}
//main
public class Main {
public static void main(String[] args) {
System.out.println("##############");
System.out.println("-------> second call:");
UserService userService = (UserService) new DynamicProxy().getProxyObject(new UserServiceImpl());
User user1 = userService.addUser();
userService.editUser(user1);
userService.deleteUser(user1.getUserId());
}
}
六、使用cglib动态代理
cglib可以代理非接口类,但是因为其实现原理是继承,所以无法代理被代理类中final方法,也无法代理final修饰的类。
代理类需要实现MethodInterceptor 接口
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.8</version>
</dependency>
</dependencies>
public class CglibDynamicProxy implements MethodInterceptor {
private Object proxied;
//Generate a new class if necessary and uses the specified callbacks (if any) to create a new object instance.
//Uses the no-arg constructor of the superclass.
//动态生成一个新的类,使用父类的无参构造方法创建一个指定了特定回调的代理实例
public Object getProxyObject(Object proxied)
{
this.proxied = proxied;
//增强器,动态代码生成器
Enhancer enhancer = new Enhancer();
//回调方法
enhancer.setCallback(this);
//设置生成类的父类类型
enhancer.setSuperclass(proxied.getClass());
//动态生成字节码并返回代理对象
return enhancer.create();
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
beforeInvoke("Object:"+o.getClass().getName());
beforeInvoke("method:"+method.getName());
beforeInvoke("args:"+convertArgs(objects));
beforeInvoke("methodProxy:"+methodProxy.getSignature());
Object result = methodProxy.invoke(this.proxied,objects);
afterInvoke("result:"+result);
return result;
}
private void beforeInvoke(String msg)
{
System.out.println("-------> beforInvoke:"+msg);
}
private void afterInvoke(String msg)
{
System.out.println("-------> afterInvoke:"+msg);
}
private String convertArgs(Object[] args)
{
if(args==null || args.length==0)
{
return null;
}
StringBuilder sb= new StringBuilder();
for(Object object : args)
{
sb.append(object.toString());
}
return sb.toString();
}
}
main:
public class Main {
public static void main(String[] args) {
System.out.println("##############");
System.out.println("-------> 4 call:");
UserService service4 = (UserService)new CglibDynamicProxy().getProxyObject(new UserServiceImpl());
User user4 = service4.addUser();
service4.editUser(user4);
service4.deleteUser(user4.getUserId());
}
}