Spring框架简介⑦

接下来进入Spring的另一核心AOP(aspect oriented programming)

面向切面编程, 通过预编译的方式在运行期通过动态代理实现的一种技术, AOP是OOP的延续, 利用AOP可以实现业务和切面的逻辑分离. 降低耦合度, 程序的重用性提高.

1 JDK动态代理

JDK动态代理的目标是接口实现类的形式

直接上代码:

代理类:

package com.rl.spring.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKProxy implements InvocationHandler {

    private Object targetObj;

    /**
     * 第一个参数: 获得目标对象的类的加载器 
     * 第二个参数: 获得目标对象的接口 
     * 第三个参数: 设置回调对象, 当前代理对象(也就是UserServiceImpl)的方法(save方法)被调用时, 会委派该参数去调用invoke
                   需要传入InvocationHandler的子类, 这里用this指代JDKProxy
     * @return
     */
    public Object createProxyInstance(Object targetObj) {
        this.targetObj = targetObj;
        return Proxy.newProxyInstance(this.targetObj.getClass().getClassLoader(),
                this.targetObj.getClass().getInterfaces(), this);
    }

    /**
     * proxy: 代理类 
     * Method: 要调用的业务方法 
     * Object[]: 调用的业务方法的参数
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 获得目标对象的get方法
        Method getMeth = this.targetObj.getClass().getMethod("getUser", null);
        // 通过反射来调用getUser
        Object user = getMeth.invoke(targetObj, null);
        Object obj = null;
        if (user != null) {
            // 业务方法返回的值
            obj = method.invoke(this.targetObj, args);
        } else {
            System.out.println("您还没有登录");
        }
        return obj;
    }
}

测试类:

package com.rl.spring.test;

import org.junit.Test;

import com.rl.spring.model.User;
import com.rl.spring.proxy.JDKProxy;
import com.rl.spring.service.UserService;
import com.rl.spring.service.impl.UserServiceImpl;

public class TestSpring {
	
    @Test
    public void Test() {
        UserServiceImpl ui = new UserServiceImpl();
        ui.setUser(new User());
        //通过业务接口来接收代理对象
        UserService userService = (UserService) new JDKProxy().createProxyInstance(ui);
        System.out.println(userService.getClass());
        userService.save();
    }
}

UserServiceImpl类

package com.rl.spring.service.impl;

import com.rl.spring.model.User;
import com.rl.spring.service.UserService;
public class UserServiceImpl implements UserService {

    private User user;
    
    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public void save() {
        System.out.println("保存用户...");
    }

    @Override
    public void update() {
        System.out.println("修改用户...");
    }
}

输出:

保存用户.../ 如果在测试代码中没有new User()的话, 则提示"您还没有登录!"

小总结:

代理类提供了一种切面针对目标对象的一种拦截并做相应处理, 在User类中并没有逻辑处理, 但却能够实现一种拦截判断是否有登录的效果, 这就是代理类的功能所在.

2 CGLIB动态代理

CGLIB可以对普通类做动态代理, 前提是目标类不能为final, 类里面的方法也不能为final

直接上代码:

代理类:

package com.rl.spring.proxy;

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 CGLIBProxy implements MethodInterceptor {

    private Object targetObj;
    
    public Object createProxyInstance(Object targetObj) {
        this.targetObj = targetObj;
        Enhancer en = new Enhancer();
        en.setSuperclass(this.targetObj.getClass());
        en.setCallback(this);
        return en.create();
    }

    @Override
    public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy arg3) throws Throwable {
        Method getMeth = this.targetObj.getClass().getMethod("getUser", null);
        Object user = getMeth.invoke(targetObj, null);
        Object obj = null;
        if(user != null) {
            obj = method.invoke(this.targetObj, arg2);
        }else {
            System.out.println("您还没有登录!");
        }
        return obj;
    }
}

测试代码:

package com.rl.spring.test;

import org.junit.Test;

import com.rl.spring.model.User;
import com.rl.spring.proxy.CGLIBProxy;
import com.rl.spring.proxy.JDKProxy;
import com.rl.spring.service.UserService;
import com.rl.spring.service.impl.UserServiceImpl;

public class TestSpring {
	
    
    @Test
    public void Test1() {
        UserServiceImpl ui = new UserServiceImpl();
        ui.setUser(new User());
        UserServiceImpl userServiceImpl = (UserServiceImpl) new CGLIBProxy().createProxyInstance(ui);
        System.out.println(userServiceImpl.getClass());
        userServiceImpl.save();
    }
}

目标对象(UserServiceImpl同上, 不列出来了), 该类可作为实现类, 也可作为普通类 CGLIB都可以对其做动态代理

猜你喜欢

转载自blog.csdn.net/ip_JL/article/details/81484010