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;
- }
- }
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>
<?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);
- }
- }
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 "";
- }
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);
- }
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 来添加日志。
测试结果如下: