解释Spring中的Aop代理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bandaotixiruiqiang/article/details/41414085

/**

 *模拟调用数据库

 */

public class UserDao {

    private Map<String,String> users=new HashMap<String,String>();

    public UserDao(){

        users.put("bandaoti", "131310");

        users.put("admin", "admin");

    }

    public voidcreate(String username,String password){

        if(users.get(username)!=null) throw newRuntimeException("user exist!");

        users.put(username,password);

    }

    public voidlogin(String username,String password){

        String pw=users.get(username);

        if(pw==null ||!pw.equals(password) )throw newRuntimeException("login failed!");

    }

    public void pring(){

        System.out.println("UserList:");

        Set<String> names=users.keySet();

        for(Stringstr:names)System.out.println(str);

    }

}

/**

 *  用户服务接口

 */

public interfaceUserService {

    void create(Stringusername,String password);

    void login(Stringusername,String password);

}

/**

 *用户接口和测试接口实例

 */

public classUserServiceImpl implements UserService ,TestInterface{

    private UserDao userDao;

    public voidsetUserDao(UserDao userDao) {

        this.userDao =userDao;

    }

    @Override

    public voidcreate(String username, String password) {

        userDao.create(username,password);

    }

    @Override

    public voidlogin(String username, String password) {

        userDao.login(username,password);

    }

    @Override

    public voidtestDoubleInterfaceInterCept() {

        System.out.println("测试拦截两个接口的其中方法");

    }

}

/**

 *创建代理对象

 */

classMyAopProxy{

    static Object createProxy(final Objectobj,final MethodBeforeAdvice methodBeforeAdvice){

        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),

                obj.getClass().getInterfaces(),//代理类实现时的接口

                newInvocationHandler() {

                    @Override

                    public Objectinvoke(Object proxy, Method method,

                            Object[] args) throws Throwable{

                        methodBeforeAdvice.before(method,args, obj);//先调用切面的before方法

                        returnmethod.invoke(obj, args);//嗲用对象的实际方法

                    }

                });

    }

}

public class test {

    public static voidmain(String[] args) {

        UserDao userDao = newUserDao();

        UserServiceImpl userService = newUserServiceImpl();

        userService.setUserDao(userDao);

        MethodBeforeAdvice log = newMethodBeforeAdvice() {

            @Override

            public voidbefore(Method m, Object[] arg1, Object arg2)

                    throws Throwable{

                System.out.println("Callmethod: " + m.getName());

            }

        };

        UserService us=(UserService)MyAopProxy.createProxy(userService,log);

        us.create("abcd", "123");

        us.login("bandaoti", "131310");

        TestInterfaceti=(TestInterface)MyAopProxy.createProxy(userService, log);

        ti.testDoubleInterfaceInterCept();

    }

}

接下来就要缕清思路了

首先是MyAopProxy类,其中有个方法为:createProxy,

最主要的就是Proxy.newProxyInstance这是实例一个代理对象,

第一个参数:类的装载器信息;第二个参数:对象的接口;第三个参数:(方法)拦截器,也就是说在执行代理对象前先执行这个拦截器(拦截器已经很普遍,不细述了)

然后中间什么Dao了,Impl了咱么都不细说了,此文章终点在于理解代理的执行过程

次解释:在测试方法中有这么一句:

MethodBeforeAdvicelog = new MethodBeforeAdvice() {

            @Override

            public voidbefore(Method m, Object[] arg1, Object arg2)

                    throws Throwable {

                System.out.println("Callmethod: " + m.getName());

            }

        };

它就是我们在MyAopProxy;createProxy方法中拦截器调用那个before方法。在执行实际方法前先执行的before方法。

在测试方法中还有这么几句:

        UserService us=(UserService)MyAopProxy.createProxy(userService,log);

       us.create("abcd""123");

        us.login("bandaoti", "131310");

        TestInterfaceti=(TestInterface)MyAopProxy.createProxy(userService, log);

        ti.testDoubleInterfaceInterCept();

在执行us.create("abcd", "123");的时候,是调用的我们自己写的,生成代理对象的类,生成的对象中的create方法。它首先执行的是拦截器中调用before方法的代码行,然后再去执行实际方法。其中调用before的方法就是我们测试类中写的log对象中的方法。SO执行时在控制台会输出Call method: create

二次解释:

接下来解释代码中为什么有个测试接口(TestInterface),其实名字是我瞎起的并不合乎常理(但它确实是用来测试的)

在测试方法的最后我们有这么两句,

TestInterfaceti=(TestInterface)MyAopProxy.createProxy(userService, log);

ti.testDoubleInterfaceInterCept();

在仔细观察UserService类实现的接口后,发现它实现了两个接口,其中就有测试接口。原因是因为有这样的一个问题:(来自《Spring2.0核心技术与最佳实践》)其中UserService充当A接口,TestInterface充当B接口

      到此,我基本把我所知道的都说出来了,虽然不够清晰。如果感觉无法忍受请立即摔碎电脑并双手不断拍胸脯大吼一声,NO~

猜你喜欢

转载自blog.csdn.net/bandaotixiruiqiang/article/details/41414085