Spring中的动态代理

  动态代理:指的就是通过一个代理对象来创建需要的业务对象,然后在这个代理对象中统一进行各种需求的处理。

  学习完Spring后会发现,Spring中的AOP(面向方面编程:Aspect Oriented Programming)是个很重要的知识点。实现AOP,我们一般采用代理的方式来实

现,这样可以减少重复代码的编写,也符合了OCP原则,即:对修改关闭,对扩展开放。其创建过程如下:

  步骤1:编写一个类实现InvocationHandler接口,例如:LogProxy类

  步骤2:在类中创建一个代理对象,例如:private Object target;

  步骤3:在类中创建一个方法来生成对象,这个方法的参数是指要代理的对象,getInstacne所返回的对象就是代理对象,例如:public static Object getInstance(Object o){ return null}

    步骤3.1:创建LogProxy对象,例如:LogProxy proxy = new LogProxy();

    步骤3.2:设置这个代理对象,例如:proxy.target = o;

    步骤3.3:通过Proxy的方法创建代理对象,第一个参数是要代理对象的classLoader,第二个参数是要代理对象实现的所有接口,第三个参数是实现类

InvocationHandler的对象,此时的result就是一个代理对象,代理的是o,例如:Object result = Proxy.newProxyInstance(o.getClass().getClassLoader(), 

o.getClass().getInterfaces(), proxy);

  步骤4:当有了代理对象之后,不管这个代理对象执行什么方法,都会调用invoke方法,只要在该方法中作相应操作就可以了。

  创建该类的具体代码如下:

    

package com.proxy;

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

public class LogProxy implements InvocationHandler {
    private Object target;
    public static Object getInstance(Object o){
        LogProxy proxy = new LogProxy();
        proxy.target=o;
        Object result = Proxy.newProxyInstance(o.getClass().getClassLoader(),
                o.getClass().getInterfaces() , proxy);
        return result;
    }
    
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Logger.info("进行了相关的操作");
        Object obj = method.invoke(target, args);
        return obj;
    }

}

接下来就是调用该类进行注入了。首先,需要在applicationContent.xml配置文件中的bean中调用LogProxy类,并且采用工厂方法的方式,即:factory-method="getInstance"。参考代码如下:

   <bean id="userDynamicDao" class="com.proxy.LogProxy" factory-method="getInstance">
           <!-- 构造方法中引用userDao -->
           <constructor-arg ref="userDao"/>
   </bean>

如果采用annotation来注入,则直接在userService类中的setUserDao方法前面加上注解:@Resource(name="userDynamicDao") 就可以了

package com.service;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import com.dao.IUserDao;
import com.model.User;
import com.sun.xml.internal.bind.v2.runtime.Name;

@Service("userService")//业务层一般用Service
public class UserService implements IUserService {
    private IUserDao userDao;
    
    public void add(User user) {
        userDao.add(user);
    }
    
    public void delete(int id) {
        
        userDao.delete(id);

    }
    
    public IUserDao getUserDao() {
        return userDao;
    }

    public User load(int id) {
        return userDao.load(id);
    }

    @Resource(name="userDynamicDao")//采用代理来注入
    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }

}

相关的类如下:

package com.model;

public class User {
    private int id;
    private String username;

    public User() {
    }
    public User(int id, String username) {
        this.id=id;
        this.username=username;
    }

    public int getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + "]";
    }
}
package com.dao;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import com.model.User;

//@Component("userDao")//等于完成了<bean id="userDao" class="com.dao.UserDao" />
@Repository("userDao")//@Repository一般用于DAO的注入
public class UserDao implements IUserDao {

    public void add(User user) {
        System.out.println("添加用户:"+user);
    }

    public void delete(int id) {
        System.out.println("删除id:"+id);
    }

    public User load(int id) {
        System.out.println("加载id:"+id);
        return null;
    }

}
package com.dao;

import com.model.User;

public interface IUserDao {
    public void add(User user);
    public void delete(int id);
    public User load(int id);
    
}
package com.proxy;

import java.util.Date;

public class Logger {
    public static void info(String info){
        System.out.println(new Date()+"---->"+info);
    }
}
package com.service;

import com.model.User;

public interface IUserService {
    public void add(User user);
    public void delete(int id);
    public User load(int id);
}

相应的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:aop="http://www.springframework.org/schema/aop"
     xmlns:context="http://www.springframework.org/schema/context"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
   <!-- 打开Spring的Annotation支持 -->
   <context:annotation-config/>
   <!-- 设定Spring 去哪些包中找Annotation -->
   <context:component-scan base-package="com"/>
   
   <bean id="userDynamicDao" class="com.proxy.LogProxy" factory-method="getInstance">
           <!-- 构造方法中引用userDao -->
           <constructor-arg ref="userDao"/>
   </bean>
</beans>

 

posted @ 2014-02-14 00:43  misterzxy  阅读(511)  评论(0编辑  收藏  举报