Spring_AOP_Proxy AOP动态代理的实现 :
动态代理指的是通过一个代理对象来创建需要的业务对象,然后在这个代理对象中统一进行各种需求的处理。
1.写一个实现相应的InvocationHandler 接口
2.创建要代理的对象
3.创建一个方法生成对象,这个方法的参数是要代理的对象,getInstance 所返回的对象就是代理对象
3.1 创建LogProxy对象
3.2设置这个代理对象
3.3 通过Proxy的方法创建代理对象,
第一个参数是要代理对象的classLoader第二个参数是要代理对象实现的所有接口,
第三个参数是实现类InvocationHander 的对象此时的result就是一个代理的对象,代理的是object
具体实现过程:
在 Spring_AOP_Proxy AOP静态代理的实现 的基础上,修改log包名为proxy,并创建LogProxy代理类并实现接口InvocationHandler:
package com.spring.proxy;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy;
import com.spring.model.LogInfo;
/**
* 1.写一个类实现InvocationHandler 接口
*
* @author sunlight
*
*/
public class LogProxy implements InvocationHandler {
// 2.创建一个代理对象
private Object target;
// 3.创建一个方法生成对象,这个方法的参数是要代理的对象,getInstance 所返回的对象就是代理对象
public static Object getInstance(Object object) {
// 3.1 创建LogProxy对象
LogProxy proxy = new LogProxy();
// 3.2设置这个代理对象
proxy.target = object;
// 3.3 通过Proxy的方法创建代理对象,第一个参数是要代理对象的classLoader
// 第二个参数是要代理对象实现的所有接口,第三个参数是实现类InvocationHander 的对象
// 此时的result就是一个代理的对象,代理的是object
Object result = Proxy.newProxyInstance(object.getClass()
.getClassLoader(), object.getClass().getInterfaces(), proxy);
return result;
}
/**
* 当有了代理对象之后,不管这个代理对象执行什么方法,都会调用以下的invoke方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if (method.getName().equals("add") || method.getName().equals("delete")
|| method.getName().equals("update")) {
Logger.info("进行了相应的操作——通过方法名称(方法执行前)");
}
Object obj = method.invoke(target, args);
if(method.isAnnotationPresent(LogInfo.class)){
LogInfo li=method.getAnnotation(LogInfo.class);
Logger.info(li.value()+"(方法执行后)");
}
return obj;
}
}
修改配置文件,添加LogProxy的注入:
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- 打开Spring的Annotation的支持 -->
<context:annotation-config />
<!-- 设定Spring去哪些包中找Annotation -->
<context:component-scan base-package="com.spring" />
<bean id="userDynamicDao" class="com.spring.proxy.LogProxy" factory-method="getInstance">
<constructor-arg ref="userDao"/>
</bean>
</beans>
修改UserService注入userDynamicDao:
package com.spring.service;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import com.spring.dao.IUserDao;
import com.spring.model.User;
//@Component(value="userService")
@Service("userService") //业务层一般用@Service注入
public class UserService implements IUserService {
private IUserDao userDao;
public IUserDao getUserDao() {
return userDao;
}
//默认通过名称注入,在JSR330中提供了@Inject来注入
//@Resource(name="userProxyDao") //此处用代理类注入
@Resource(name="userDynamicDao")
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
@Override
public void add(User user) {
userDao.add(user);
}
@Override
public void delete(int id) {
userDao.delete(id);
}
@Override
public User load(int id) {
return userDao.load(id);
}
}
编写简单的注解 LogInfo:
package com.spring.model;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface LogInfo {
public String value() default "";
}
IUserDao接口添加注解,添加了LogInfo注解的方法可以为其添加日志。
package com.spring.dao;
import com.spring.model.LogInfo;
import com.spring.model.User;
public interface IUserDao {
@LogInfo("添加了用户信息——注解方式")
public void add(User user);
@LogInfo("删除了用户信息——注解方式")
public void delete(int id);
public User load(int id);
}
以上是动态代理的2中实现:
1.通过方法名称来添加日志;
2.通过注解方式来添加日志;
注意,AOP的动态代理实现,添加日志操作可以在方法执行前,也可以在方法执行后,本例 方法前使用 1 来添加日志,方法后使用 2 来添加日志。
测试结果如下: