属性编辑器: PropertyEditorSupport 作用:如果一个类中的属性为Date类型,那么在beans.xml中设置的Date值不能与Date匹配,那么我们需要对beans.xml中的属性进行编辑,让它转化为Date类型的 CustomEditorConfigurer可以读取实现java.beans.PropertyEditor接口的类,将字符串转为指定的类型,更方便的使用PropertyEditorSupport.PropertyEditorSupport实现PropertyEditor,必须重新定义setAsText 程序目标:如果bean类中有不是一般类型的属性的话,并且在xml文件中有这个属性的赋值,那么可以使用属性编辑器对属性进行类型的封装,然后通过org.springframework.beans.factory.config.CustomEditorConfigurer类在xml中与属性编辑器处理类绑定 接口: package yuchen.dataeditor; public interface A { public void display(); } 实现类: package yuchen.dataeditor; import java.util.Date; public class AImp implements A { private Date date; public void display() { // TODO Auto-generated method stub if(date instanceof Date){ System.out.println(date); } } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } } 属性编辑器类 package yuchen.dataeditor; import java.beans.PropertyEditorSupport;//属性编辑器 import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; public class DateEditor extends PropertyEditorSupport { private Date date; @Override public void setAsText(String str) throws IllegalArgumentException { // TODO Auto-generated method stub String[] a=str.split("/"); int year = Integer.parseInt(a[0]); int month = Integer.parseInt(a[1]); int day = Integer.parseInt(a[2]); Calendar cal= new GregorianCalendar(year,month-1,day); date = cal.getTime(); } @Override public Object getValue() { // TODO Auto-generated method stub return date; } } xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd" > <beans> <bean id="a" class="yuchen.dataeditor.AImp"> <property name="date"> <value> </property> </bean> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.util.Date"> <bean class="yuchen.dataeditor.DateEditor"/> </entry> </map> </property> </bean> </beans> Test: package yuchen.dataeditor; /* * 属性编辑器:java.beans.PropertyEditorSupport * 如何知道属性编辑器类为谁服务呢? * <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.util.Date"> <bean class="yuchen.dataeditor.DateEditor"/> </entry> </map> </property> </bean> */ import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("yuchen/dataeditor/beans.xml"); A aa=(A) context.getBean("a"); aa.display(); } } 属性设置器: 除了通过beans.xml设置属性以外,还可以通过PropertyPlaceholderConfigurer为bean属性设置值,它利用属性文件 程序目标:测试PropertyPlaceholderConfigurer类 接口: package yuchen.propertyphc; public interface A { public void display(); } 实现类: package yuchen.propertyphc; import java.util.Date; public class AImp implements A { private Date date; public void display() { // TODO Auto-generated method stub if(date instanceof Date){ System.out.println(date); } } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } } 属性编辑器: package yuchen.propertyphc; import java.beans.PropertyEditorSupport;//属性编辑器 import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; public class DateEditor extends PropertyEditorSupport { private Date date; @Override public void setAsText(String str) throws IllegalArgumentException { // TODO Auto-generated method stub String[] a=str.split("/"); int year = Integer.parseInt(a[0]); int month = Integer.parseInt(a[1]); int day = Integer.parseInt(a[2]); Calendar cal= new GregorianCalendar(year,month-1,day); date = cal.getTime(); } @Override public Object getValue() { // TODO Auto-generated method stub return date; } } 属性文件: date= xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd" > <beans> <bean id="a" class="yuchen.propertyphc.AImp"> <property name="date"> <value>${date}</value> </property> </bean> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.util.Date"> <bean class="yuchen.propertyphc.DateEditor"/> </entry> </map> </property> </bean> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigur er"> <property name="locations"> <list> <value>yuchen/propertyphc/AImp.properties</value> </list> </property> </bean> </beans> Test: package yuchen.propertyphc; /* * 属性设置器: * 通过属性文件给bean的属性设置值 * 在beans.xml中添加属性设置器类: * <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigur er"> <property name="locations"> <list> <value>yuchen/propertyphc/AImp.properties</value> </list> </property> </bean> 属性文件: date= */ import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("yuchen/propertyphc/beans.xml"); A aa=(A) context.getBean("a"); aa.display(); } } 属性覆盖器: 作用:属性文件中设置好的属性值将会覆盖掉beans.xml中类属性值 接口: package yuchen.propertypoc; public interface A { public void display(); } 实现类: package yuchen.propertypoc; import java.util.Date; public class AImp implements A { private String name; public void display() { // TODO Auto-generated method stub System.out.println(this.name); } public String getName() { return name; } public void setName(String name) { this.name = name; } } xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd" > <beans> <bean id="a" class="yuchen.propertypoc.AImp"> <property name="name"> <value>zhao</value> </property> </bean> <bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer" > <property name="location"> <value>yuchen/propertypoc/AImp.properties</value> </property> </bean> </beans> 属性文件: a.name=yuchen Test: package yuchen.propertypoc; /* * 覆盖: * 使用PropertyOverrideConfigurer那么属性文件中设置的属性值 * 会覆盖在beans.xml 的bean类中设置的属性值 */ import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("yuchen/propertypoc/beans.xml"); A aa=(A) context.getBean("a"); aa.display(); } } ApplicationContext的事件特性(观察者模式): 1.ApplicationContext发布事务 2.事件响应者需要实现ApplicationListener 3.定义一个事件类,继承ApplicationEvent 接口: package yuchen.event; public interface Model { public String superDate(); public void update(); } 接口: package yuchen.event; public interface View { public void display(); } 实现类: package yuchen.event; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationEvent; public class ModelImpl implements Model,ApplicationContextAware{ private String name; private ApplicationContext context; public String superDate() { // TODO Auto-generated method stub return name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void update(){ this.setName("zhang"); if(context!=null){ context.publishEvent(new RefreshEvent(this,"update ()")); }else{ System.out.println("null"); } } public void setApplicationContext(ApplicationContext arg0) throws BeansException { // TODO Auto-generated method stub context=arg0; } } 实现类: package yuchen.event; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; public class ViewImpl implements View,ApplicationListener{ private Model model; public void display() { // TODO Auto-generated method stub String rst=model.superDate(); System.out.println(rst); } public Model getModel() { return model; } public void setModel(Model model) { this.model = model; } public void onApplicationEvent(ApplicationEvent arg0) { // TODO Auto-generated method stub if(arg0 instanceof RefreshEvent){ System.out.println("事件发生后调用onApplicationEvent方法"); this.display(); } } } 事件类: package yuchen.event; import org.springframework.context.ApplicationEvent; public class RefreshEvent extends ApplicationEvent{ private String message; public RefreshEvent(Object arg0,String message) { super(arg0); this.message=message; // TODO Auto-generated constructor stub } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd" > <beans> <bean id="model" class="yuchen.event.ModelImpl"> <property name="name"> <value>yuchen</value> </property> </bean> <bean id="view" class="yuchen.event.ViewImpl"> <property name="model"> <ref bean="model"></ref> </property> </bean> </beans> Test: package yuchen.event; /* * 程序目标:当更新model里的name时,context发布事件,再次调用display方法 * ApplicationContext用来发布事件 * ApplicationEvent为事件的抽象类,需要继承此类声明一个事件对象 * ApplicationListener监听器监听是否有事件发生,当context发布事件 * 后,会调用实现了此接口的bean中的onApplicationEvent()方法 * 实现ApplicationContextAware的类可获得context */ import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { /** * @param args */ public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("yuchen/event/beans.xml"); View v=(View) context.getBean("view"); v.display(); System.out.println("----------------"); ModelImpl m=(ModelImpl)context.getBean("model"); m.update(); } } 国际化: ApplicationContext的getMessage方法可以做国际化 并且在beans.xml中需要配置国际化文件的路径 修改上面的类:将消息的内容国际化 ModelImpl.java: public void update(){ this.setName("zhang"); if(context!=null){ //context.publishEvent(new RefreshEvent(this,"update()")); context.publishEvent(new RefreshEvent(this,context.getMessage("message", new String[]{"message","!!!!!"}, Locale.CHINA))); }else{ System.out.println("null"); } } 加入国际化属性文件: message_zh.properties: message = {0} \u5237\u65b0 {1} Message_en.properties: message = {0} refresh{1} 修改beans.xml: 加入: <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>yuchen/event/message</value> </list> </property> </bean> 工厂bean: 以前的程序都是通过容器产生工厂,容器的表现有两种 1.XmlBeanFactory 2.ApplicationContext 现在不用得到工厂,通过一个工厂bean去得到bean实例 产生的实例为工厂bean创建的产品,并不是工厂对象 package yuchen.factorybean; import java.util.Properties; import org.springframework.beans.factory.FactoryBean; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; Test: public class Test { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { ApplicationContext factory = new ClassPathXmlApplicationContext("yuchen/factorybean/beans.xml"); long s = (Long)factory.getBean("a"); System.out.println(s); String classpath = (String)factory.getBean("classpath"); System.out.println(classpath); FactoryBean o =(FactoryBean)factory.getBean("&classpath"); String classpath2 = (String)o.getObject(); System.out.println(classpath2); } } beans.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd" > <beans> <bean id="a" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetClass"><value>java.lang.System</value></property> <property name="targetMethod"><value>currentTimeMillis</value></property> </bean> <bean id="props" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetClass" value="java.lang.System"></property> <property name="targetMethod" value="getProperties"/> </bean> <bean id="classpath" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetObject"><ref local="props"/></property> <property name="targetMethod" value="getProperty"></property> <property name="arguments"> <value>java.class.path</value> </property> </bean> </beans> 面向方面编程AOP: 1.什么是面向方面编程?有什么用? 2.一个陈旧的案例 3.AOP的一些概念 4.第一个AOP程序 5.前置Advice 6.后置Advice 7.环绕Advice 8.异常抛出Advice 什么是面向方面编程?有什么用? 面向方面编程就是就是将类中掺杂的与业务无关的代码抽象出来,以便重用 作用:重用,解耦合 包含两个要素: 1.在哪里加入服务(方法前?方法后?属性?) 2.具体为哪个类的哪个方法或属性加入服务 例如: 1.要在方法前加入事务服务 2.为A类的sayhello()业务方法加入服务 两者组合就是一个方面 一个陈旧的案例: 程序目标:为A类的业务方法1加入事务和安全的服务,为业务方法2只加入事务的服务 package yuchen.aop.oldcase; public class OldCase { public void execute1(){ safetybackcheck(); System.out.println("事务开始代码"); this.operation1(); System.out.println("事务结束代码"); } public void execute2(){ System.out.println("事务开始代码"); this.operation2(); System.out.println("事务结束代码"); } public void safetybackcheck(){ System.out.println("安全检查代码"); } public void operation1(){ System.out.println("业务代码1"); } public void operation2(){ System.out.println("业务代码2"); } } 发现问题:业务代码和服务代码互相掺杂,结构不清晰,维护代码不方便,也不方便重用 那么使用AOP编程就是为了解决这个问题 AOP的一些概念: 关注点:业务核心代码(如: operation1)和系统服务代码(事务,安全代码)都是关注点 横切关注点:程序中的系统服务代码都是横切关注点 核心关注点:就是业务核心代码 方面(aspect):advice+pointcut=aspect,一个方面说明了为哪些类的哪些方法,属性等加入哪些服务,例如:为A类的a()方法加入事务,安全服务,这就是方面 advice: 在哪里加入服务(方法前?方法后?属性?),就是拦截器 pointcut: 具体为哪个类的哪个方法或属性加入服务 连接点:能插入服务的位置是连接点:如:方法,属性,异常抛出,Spring Aop只支持一种类型的连接点(方法) 织入(weaving):就是将方面加入到具体的哪个对象中 Aop代理:Aop Proxy:代理对象,他去调用被包装了服务的业务方法 AOP的目标就是要将横切关注点与核心关注点分离,实现解耦合,重用这些服务 第一个AOP程序: 接口: package yuchen.aop.firstaop; public interface Business { public void business1(); public void business2(); } 核心业务类: package yuchen.aop.firstaop; public class BusinessImpl implements Business { public void busMethod1(){ this.business1(); } public void busMethod2(){ this.business2(); } public void business1() { // TODO Auto-generated method stub System.out.println("核心业务方法1"); } public void business2() { // TODO Auto-generated method stub System.out.println("核心业务方法2"); } } 安全服务: package yuchen.aop.firstaop; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class SecuityBeforeAdvice implements MethodBeforeAdvice{ public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable { // TODO Auto-generated method stub this.check(); } public void check(){ System.out.println("安全检查"); } } 事务服务: package yuchen.aop.firstaop; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class AffairAroundAdvice implements MethodInterceptor{ public Object invoke(MethodInvocation arg0) throws Throwable { // TODO Auto-generated method stub this.transactionStart(); Object object=arg0.proceed(); this.transactionEnd(); return object; } public void transactionStart(){ System.out.println("事务开始"); } public void transactionEnd(){ System.out.println("事务结束"); } } 事务服务pointcut: package yuchen.aop.firstaop; import java.lang.reflect.Method; import org.springframework.aop.ClassFilter; import org.springframework.aop.support.StaticMethodMatcherPointcut; public class PointcutImpl extends StaticMethodMatcherPointcut{ public boolean matches(Method arg0, Class arg1) { // TODO Auto-generated method stub if(arg0.getName().equals("business1")){ return true; } return false; } @Override public ClassFilter getClassFilter() { // TODO Auto-generated method stub return new ClassFilter(){ public boolean matches(Class arg0) { // TODO Auto-generated method stub return (arg0==BusinessImpl.class); } }; } } Test: package yuchen.aop.firstaop; /* * 为类中的某些方法加上事务和安全 */ import org.springframework.aop.Advisor; import org.springframework.aop.Pointcut; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.support.DefaultPointcutAdvisor; public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ProxyFactory pf=new ProxyFactory(); Business bi=new BusinessImpl(); SecuityBeforeAdvice sb=new SecuityBeforeAdvice(); Pointcut p=new PointcutImpl(); Advisor advisor=new DefaultPointcutAdvisor(p,sb); AffairAroundAdvice ad=new AffairAroundAdvice(); pf.addAdvisor(advisor); pf.addAdvice(ad); pf.setTarget(bi); Business b=(Business) pf.getProxy(); b.business1(); b.business2(); } } 开发步骤: 1.写核心业务类 2.写系统服务类(advice) 3.选择性的写过滤类(pointcut) 4.写客户代码:通过DefaultPointcutAdvisor将advice and pointcut组装,代理工厂添加advice,设置目标对象,生成代理对象,代理对象调用业务方法 使用proxyfactorybean方式: 添加配置文件: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd" > <beans> <bean id="businessimpl" class="yuchen.aop.updatefirstaop.BusinessImpl"> </bean> <bean id="secuity" class="yuchen.aop.updatefirstaop.SecuityBeforeAdvice"> </bean> <bean id="affair" class="yuchen.aop.updatefirstaop.AffairAroundAdvice"> </bean> <bean id="pointcutimpl" class="yuchen.aop.updatefirstaop.PointcutImpl"> </bean> <bean id="befadvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="advice"> <ref local="secuity"></ref> </property> <property name="pointcut"> <ref local="pointcutimpl"></ref> </property> </bean> <bean id="factory" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <ref bean="businessimpl"></ref> </property> <property name="interceptorNames"> <list> <value>befadvisor</value> <value>affair</value> </list> </property> </bean> </beans> 修改Test: package yuchen.aop.updatefirstaop; import org.springframework.aop.Advisor; import org.springframework.aop.Pointcut; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ApplicationContext context=new ClassPathXmlApplicationContext("yuchen/aop/updatefirstaop/beans.xml"); Business b=(Business) context.getBean("factory"); b.busMethod1(); } } 前置Advice: 接口: package yuchen.aop.before.proxyfactory; public interface Business { public void busMethod1(); public void busMethod2(); } 核心业务实现类: package yuchen.aop.before.proxyfactory; public class BusinessImpl implements Business { public void busMethod1(){ this.business1(); } public void busMethod2(){ this.business2(); } public void business1() { // TODO Auto-generated method stub System.out.println("核心业务方法1"); } public void business2() { // TODO Auto-generated method stub System.out.println("核心业务方法2"); } } 实体类: package yuchen.aop.before.proxyfactory; public class UserInfo { private String username; private String password; public UserInfo() { super(); } public UserInfo(String username, String password) { super(); this.username = username; this.password = password; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } } 用户登陆管理类: package yuchen.aop.before.proxyfactory; public class UserMagager { private static ThreadLocal t=new ThreadLocal(); public static void login(String username,String password){ t.set(new UserInfo(username,password)); } public static void logout(){ t.set(null); } public static UserInfo getUserInfo(){ return (UserInfo)t.get(); } public static void validate(){ UserInfo user=getUserInfo(); if(user==null){ throw new UserInfoException("您还没有登陆"); }else if(user.getUsername().equals("admin")){ System.out.println("系统管理员登陆"); }else{ throw new UserInfoException("您不是系统管理员"); } } } 自定义异常: package yuchen.aop.before.proxyfactory; public class UserInfoException extends RuntimeException { public UserInfoException(String msg){ super(msg); } } 前置advice: package yuchen.aop.before.proxyfactory; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class SecuityBeforeAdvice implements MethodBeforeAdvice{ public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable { // TODO Auto-generated method stub UserMagager.validate(); } } Test: package yuchen.aop.before.proxyfactory; /* * 当抛出异常的时候,拦截器中断 */ import org.springframework.aop.framework.ProxyFactory; public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Business bi=getProxyFactory(); try{ bi.busMethod1(); }catch(UserInfoException ue){ System.out.println(ue.getMessage()); } UserMagager.login("admin", "1234"); bi.busMethod1(); UserMagager.logout(); UserMagager.login("yuchen", "123"); try{ bi.busMethod1(); }catch(UserInfoException ue){ System.out.println(ue.getMessage()); } } public static Business getProxyFactory(){ ProxyFactory pf=new ProxyFactory(); Business business=new BusinessImpl(); SecuityBeforeAdvice sa=new SecuityBeforeAdvice(); pf.setTarget(business); pf.addAdvice(sa); return (Business)pf.getProxy(); } } 采用声明服务方式: xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd" > <beans> <bean id="businessimpl" class="yuchen.aop.before.proxyfactorybean.BusinessImpl"> </bean> <bean id="secuity" class="yuchen.aop.before.proxyfactorybean.SecuityBeforeAdvice"> </bean> <bean id="factory" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <ref bean="businessimpl"></ref> </property> <property name="interceptorNames"> <list> <value>secuity</value> </list> </property> </bean> </beans> 修改Test: package yuchen.aop.before.proxyfactorybean; /* * 当抛出异常的时候,拦截器中断 */ import org.springframework.aop.framework.ProxyFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("yuchen/aop/before/proxyfactorybean/beans.xml"); Business business=(Business) context.getBean("factory"); UserMagager.login("admin", "123"); business.busMethod1(); business.busMethod2(); UserMagager.logout(); UserMagager.login("yuchen", "1"); try{ business.busMethod1(); }catch(UserInfoException ue){ System.out.println(ue.getMessage()); } UserMagager.logout(); try{ business.busMethod1(); }catch(UserInfoException ue){ System.out.println(ue.getMessage()); } } } 后置Advice: 实体类: package yuchen.aop.after.proxyfactory; /* * 业务类 */ public class Man { private String name; private int age; public Man() { super(); } public Man(String name, int age) { super(); this.name = name; this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Man growup(){ ++age; return this; } } 核心业务类: package yuchen.aop.after.proxyfactory; /** * 服务:方法计数器 */ import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; public class Counter { private static Map countmap=new HashMap();//存方法名和调用次数 public Map getCountmap() { return countmap; } public void setCountmap(Map countmap) { this.countmap = countmap; } public void count(Method method){ count(method.getName()); } //计算方法调用的次数并保存到一个map表中 public void count(String name){ Integer i=(Integer) countmap.get("name"); if(i!=null){ countmap.put(name, new Integer(i.intValue()+1)); }else{ countmap.put(name, 1); } } //返回方法调用的次数 public int getCount(String name){ int x; Integer i=(Integer) countmap.get(name); if(i==null){ x=0; }else{ x=i.intValue(); } return x; } } 后置advice: package yuchen.aop.after.proxyfactory; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; public class CountAgeAfterAdvice extends Counter implements AfterReturningAdvice{ public void afterReturning(Object returnvalue, Method method, Object[] parameter, Object target) throws Throwable { // TODO Auto-generated method stub //returnvalue:被拦截的方法的返回值 //method:被拦截的方法 //parameter:被拦截的方法的参数 //target:被拦截的目标对象 this.count(method);//被拦截的对象的方法调用后执行 if(method.getName().equals("growup")){ Man man=(Man)returnvalue; System.out.println(man.getName()+":"+man.getAge()); System.out.println(this.getCount(method.getName())); } } } Test: package yuchen.aop.after.proxyfactory; import org.aopalliance.aop.Advice; import org.springframework.aop.framework.ProxyFactory; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub Man man=new Man("yuchen",24); CountAgeAfterAdvice counter=new CountAgeAfterAdvice(); ProxyFactory pf=new ProxyFactory(); pf.addAdvice(counter); pf.setTarget(man); Man m=(Man) pf.getProxy(); m.growup(); } } 声明式:xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd" > <beans> <bean id="man" class="yuchen.aop.after.proxyfactorybean.Man"> <property name="name"> <value>yuchen</value> </property> <property name="age"> <value>24</value> </property> </bean> <bean id="counterage" class="yuchen.aop.after.proxyfactorybean.CountAgeAfterAdvice"> </bean> <bean id="factory" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <ref bean="man"></ref> </property> <property name="interceptorNames"> <list> <value>counterage</value> </list> </property> </bean> </beans> 修改Test: package yuchen.aop.after.proxyfactorybean; import org.aopalliance.aop.Advice; import org.springframework.aop.framework.ProxyFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub ApplicationContext context=new ClassPathXmlApplicationContext("yuchen/aop/after/proxyfactorybean/beans.xml"); Man man=(Man) context.getBean("factory"); System.out.println(man.getName()+":"+man.getAge()); man.growup(); } } 环绕Advice: 业务核心类: package yuchen.aop.interception.proxyfactory; public class AccountWork { public void account(int num){ for(int i=0;i<num;i++){ work(); } } public void work(){ System.out.println("工作中...."); } } 环绕advice: package yuchen.aop.interception.proxyfactory; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.util.StopWatch; public class AccountCapabilityAdvice implements MethodInterceptor{ public Object invoke(MethodInvocation invocation) throws Throwable { // TODO Auto-generated method stub StopWatch sw=new StopWatch(); sw.start(invocation.getMethod().getName()); Object obj=invocation.proceed(); sw.stop(); this.displaybulletin(invocation, sw.getTotalTimeMillis()); return obj; } private void displaybulletin(MethodInvocation invocation,long l){ Method m=invocation.getMethod(); Object obj=invocation.getThis(); Object[] arg=invocation.getArguments(); System.out.println("目标类:"+obj.getClass().getName()); System.out.println("方法:"+m.getName()); System.out.print("方法参数:"); for(int i=0;i<arg.length;i++){ System.out.print(arg[i]); if(i!=arg.length-1){ System.out.println(","); }else{ System.out.println("."); } } System.out.println("性能测试时间:"+l); } } Test: package yuchen.aop.interception.proxyfactory; import org.springframework.aop.framework.ProxyFactory; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub AccountWork aa=getproxyfactory(); aa.account(100); } private static AccountWork getproxyfactory(){ ProxyFactory pf=new ProxyFactory(); AccountWork aw=new AccountWork(); AccountCapabilityAdvice aca=new AccountCapabilityAdvice(); pf.setTarget(aw); pf.addAdvice(aca); return (AccountWork)pf.getProxy(); } } 声明方式: xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd" > <beans> <bean id="account" class="yuchen.aop.interception.proxyfactorybean.AccountWork"> </bean> <bean id="acadvice" class="yuchen.aop.interception.proxyfactorybean.AccountCapabilityAdvice"> </bean> <bean id="factory" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <ref bean="account"></ref> </property> <property name="interceptorNames"> <list> <value>acadvice</value> </list> </property> </bean> </beans> 修改Test: package yuchen.aop.interception.proxyfactorybean; import org.springframework.aop.framework.ProxyFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub ApplicationContext context=new ClassPathXmlApplicationContext("yuchen/aop/interception/proxyfactorybean/beans.xml"); AccountWork aw=(AccountWork) context.getBean("factory"); aw.account(100); } } 异常抛出Advice: 业务核心类: package yuchen.aop.exception.proxyfactory; import java.rmi.RemoteException; public class ExceptionBean { public void exception1() throws RemoteException{ throw new RemoteException("远程方法调用异常"); } } 异常抛出advice: package yuchen.aop.exception.proxyfactory; import java.lang.reflect.Method; import java.rmi.RemoteException; import org.springframework.aop.ThrowsAdvice; public class ExceptionAdvice implements ThrowsAdvice{ public void afterThrowing(Method method,Object[] args,Object target,RemoteException re){ System.out.println("抛出异常的方法名:"+method); System.out.println("目标对象:"+target.getClass().getName()); System.out.println("异常信息:"+re.getMessage()); } } Test: package yuchen.aop.exception.proxyfactory; import java.rmi.RemoteException; import org.springframework.aop.framework.ProxyFactory; public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ExceptionBean bean=getProxyFactory(); try { bean.exception1(); } catch (RemoteException e) { // TODO Auto-generated catch block } } public static ExceptionBean getProxyFactory(){ ProxyFactory pf=new ProxyFactory(); ExceptionBean eb=new ExceptionBean(); ExceptionAdvice ea=new ExceptionAdvice(); pf.setTarget(eb); pf.addAdvice(ea); return (ExceptionBean)pf.getProxy(); } } 声明式方式: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd" > <beans> <bean id="bean" class="yuchen.aop.exception.proxyfactorybean.ExceptionBean"> </bean> <bean id="advice" class="yuchen.aop.exception.proxyfactorybean.ExceptionAdvice"> </bean> <bean id="factory" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <ref bean="bean"></ref> </property> <property name="interceptorNames"> <list> <value>advice</value> </list> </property> </bean> </beans> 修改Test: package yuchen.aop.exception.proxyfactorybean; import java.rmi.RemoteException; import org.springframework.aop.framework.ProxyFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ApplicationContext context=new ClassPathXmlApplicationContext("yuchen/aop/exception/proxyfactorybean/beans.xml"); ExceptionBean bean=(ExceptionBean) context.getBean("factory"); try { bean.exception1(); } catch (RemoteException e) { // TODO Auto-generated catch block } } |
|