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>