aop编程 之使用spring框架实现方法调用前日志输出
使用spring框架实现AOP编程首先需要搭建spring框架环境:
使用Spring框架实现AOP工程编程之后,不需要我们去写代理工厂了,工厂的实例化由spring框架完成。
spring框架生成代理对象的秘密:
1. 如果面向接口编程,那么底层采用jdk动态代理生成目标对象
2. 如果没有面向接口编程,那么底层采用cglib动态代理生成目标对象
由于spring的封装,使得我们实现AOP编程变得简单。
搭建Spring环境:引入Jar包,并且添加到构建路径中去
面向接口编程的方式(底层采用jdk动态代理生成目标对象)
首先编写目标对象的接口UserDaoIfac,添加一个删除用户的方法
package net.neuedu.spring.test;
public interface UserDaoIfac {
Integer deleteUser(Integer userId);
}
编写目标对象,实现刚刚写的接口
package net.neuedu.spring.test;
public class UserDao implements UserDaoIfac {
@Override
public Integer deleteUser(Integer userId)
{
System.out.println("deleteUser:"+userId);
return userId;
}
}
编写日志输出类LogOutput,实现MethodBeforeAdvice(前置通知的接口)并且实现它的接口
package net.neuedu.spring.test;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.aop.MethodBeforeAdvice;
public class LogOutput implements MethodBeforeAdvice {
private Logger log=Logger.getLogger("net.neuedu.spring.test.LogOutput");
//net.neuedu.spring.test.LogOutput这个是日志输出的对象
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
log.log(Level.INFO,"日志输出");
}
}
接下来配置beans.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 实例化UserDao -->
<bean id="userDao" class="net.neuedu.spring.test.UserDao">
</bean>
<!-- 实例化LogOutput对象 -->
<bean id="logOutput" class="net.neuedu.spring.test.LogOutput"></bean>
<!-- userDao代理对象,需要配三个参数
proxyInterfaces:代理对象的接口,由spring代理工厂提供
interceptorNames:拦截器名称,日志输出就是拦截器
target:目标对象,userDao就是目标对象
-->
<bean id="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="net.neuedu.spring.test.UserDaoIfac"></property>
<property name="interceptorNames">
<list>
<value>logOutput</value>
</list>
</property>
<property name="target" ref="userDao"></property>
</bean>
</beans>
编程测试类, 如下:
package net.neuedu.spring.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext act=new ClassPathXmlApplicationContext("beans.xml");
UserDaoIfac userDaoProxy=(UserDaoIfac) act.getBean("userDaoProxy");
userDaoProxy.deleteUser(100);
}
}
看控制台输出结果:
不面向接口编程(底层采用cglib动态代理生成目标对象)
那么接下来 就是不面向接口编程的方法
编写一个BookDao类
package net.neuedu.spring.test;
//不面向接口编程
public class BookDao {
public void addBook(String bookName)
{
System.out.println("添加图书:"+bookName);
}
}
日输出类LogOutput,并且实现MethodBeforeAdvice接口(与前面的LogOutput一样)
package net.neuedu.spring.test;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.aop.MethodBeforeAdvice;
public class LogOutput implements MethodBeforeAdvice {
private Logger log=Logger.getLogger("net.neuedu.spring.test.LogOutput");
//net.neuedu.spring.test.LogOutput这个是日志输出的对象
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
log.log(Level.INFO,"调用方法之前日志输出+++++++++++++");
}
}
配置beans.xml文件:
不面向接口编程配置xml文件会更加简单,只需要配置拦截器和目标对象即可,代码如下:
<bean id="bookDao" class="net.neuedu.spring.test.BookDao"></bean>
<bean id="bookDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="bookDao"></property>
<property name="interceptorNames">
<list>
<value>logOutput</value>
</list>
</property>
</bean>
编写测试类:
package net.neuedu.spring.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext act=new ClassPathXmlApplicationContext("beans.xml");
BookDao bookDaoProxy=(BookDao) act.getBean("bookDaoProxy"); //获取代理对象
bookDaoProxy.addBook("水浒传");
}
}
结果如下: