spring的几个通知
spring的通知相当于struts2的拦截器。原理都是执行目标对象的方法时先执行一些操作或者目标对象方法执行后再去执行其他操作。
spring的通知又分为前置通知(目标对象方法执行前执行),后置通知(目标对象方法执行后执行),异常通知(目标对象如果发生异常则执行),环绕通知(可以选择是否执行目标对象的方法)。
实现spring的通知分为三步:
第一步:建立目标对象类,这里设为UserDaoBean.java。
第二步:创建通知类,BeforeAdviceExample(前置通知类),AfterAdviceExamplel(后置通知类),ThrowsAdviceExample(异常通知类)。这三个类都要实现各自的接口,和重写某些方法。
第三步:创建代理对象类,该类是spring内部提供的,我们只需要在配置文件中配置好就可以使用。代理类是目标类和通知类的纽带。只有通过代理类才可以关联他们。
目标类UserDaoBean.java具体代码如下:
package cn.itcast.dao.impl; import java.util.List; import java.util.Map; import java.util.Properties; public class UserDaoBean { private String name; private int age; private List list; private Map map; private Properties properties; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public List getList() { return list; } public void setList(List list) { this.list = list; } public Map getMap() { return map; } public void setMap(Map map) { this.map = map; } public Properties getProperties() { return properties; } public void setProperties(Properties properties) { this.properties = properties; } //调用那个方法哪个方法就被拦截 public void run(){ System.out.println("我是run方法"); } public void run(String str){ System.out.println("我是run方法"+str); } }
前置通知类代码:
package cn.itcast.dao.impl; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class BeforeAdviceExample implements MethodBeforeAdvice { @Override /** * method 目标对象执行的方法 * args 方法的参数 * target 目标对象类型 */ public void before(Method method, Object[] args, Object target) throws Throwable { System. out.println(target.getClass()); System. out.println(method + "will running!"); } }
后置通知代码:
package cn.itcast.dao.impl; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; /** * 后置通知类,目标对象的方法执行完后才执行 * @author Administrator * */ public class AfterAdviceExamplel implements AfterReturningAdvice{ @Override /** * 在 afterReturning ()方法中有 4 个参数,returnValue 指本方法的返回值, target * 指目标对象, method 和 args 是分别是该对象的方法和参数。 */ public void afterReturning(Object returnValue, Method method, Object[] args,Object target) throws Throwable { System.out.println("后置通知目标对象的类型="+target.getClass()); System.out.println("目标对象执行的方法="+method + "was running!"); System.out.println("目标对象执行方法的参数="+args[0].toString()); } }
异常通知代码:
package cn.itcast.dao.impl; import org.springframework.aop.ThrowsAdvice; import java.lang.reflect.Method; //throw通知类。目标类抛出异常的时候执行 public class ThrowsAdviceExample implements ThrowsAdvice { public void afterThrowing(Method method,Object[] args, Object target,Throwable subclass){ System.out.println(target.getClass()+"异常通知类代码执行"); } }
最后注意看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-2.5.xsd"> <bean id="personDao" class="cn.itcast.dao.impl.PersonDaoBean"></bean> <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"> <!-- 使用内部bean进行注入 <property name="personDao"> <bean class="cn.itcast.dao.impl.PersonDaoBean"/> </property> --> <property name="personDao" ref="personDao"/> <property name="name" value="itcast"/> <property name="id" value="88"/> </bean> <!-- 目标类 --> <bean id="userDao" class="cn.itcast.dao.impl.UserDaoBean"> <property name="name" value="wukailing"></property> <property name="age" value="22"></property> <!-- 普通list属性注入 --> <property name="list"> <list> <value>123</value> <value>456</value> <value>789</value> </list> </property> <!-- Map属性注入 --> <property name="map"> <map> <entry key="key1"> <value>wukailing</value> </entry> <entry key="key2"> <value>wukaiyi</value> </entry> </map> </property> <!-- props --> <property name="properties"> <props> <prop key="key1">student1</prop> <prop key="key2">student2</prop> </props> </property> </bean> <!-- 创建前置通知类 --> <bean id="advice" class="cn.itcast.dao.impl.BeforeAdviceExample"> </bean> <!-- 创建异常(后置)通知类 --> <bean id="throwAdvice" class="cn.itcast.dao.impl.ThrowsAdviceExample"> </bean> <!-- 创建后置通知类 --> <bean id="after" class="cn.itcast.dao.impl.AfterAdviceExamplel"> </bean> <!-- 创建代理对象,他是目标对象和通知类的纽带 --> <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <ref bean="userDao"/><!-- 目标对象bean的名称 --> </property> <property name="interceptorNames"> <list> <value>advice</value><!-- 创建通知类bean的名称 --> <value>throwAdvice</value> <value>after</value> </list> </property> </bean> </beans>
测试:
测试的时候需要注意:
不是直接拿目标对象的bean,而是拿代理对象类的bean,然后强制转为目标对象的bean
package test; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.itcast.dao.impl.UserDaoBean; import cn.itcast.service.impl.PersonServiceBean; public class Mytest { private static ApplicationContext as; static{ as = new ClassPathXmlApplicationContext("beans.xml"); } public static void main(String args[]){ // PersonServiceBean personServiceBean = (PersonServiceBean)as.getBean("personService"); // personServiceBean.save(); UserDaoBean userDaoBean = (UserDaoBean)as.getBean("userDao"); //System.out.println(userDaoBean.getAge()); /*List<String > list = userDaoBean.getList(); for(String str:list){ System.out.println(str); } Map map = userDaoBean.getMap(); Set<String > set = map.keySet(); for(String key : set){ String value = (String)map.get(key); System.out.println(key+"="+value); } Properties properties = userDaoBean.getProperties(); System.out.println(properties);*/ //userDaoBean.run(); UserDaoBean userDaoBean2 = (UserDaoBean)as.getBean("proxyFactoryBean");//目标对象的bean名称 userDaoBean2.run("123456"); } }