Spring的第二讲

所学知识点:

1.使用spring的特殊bean

1.   》分散配置

2.   》定制属性编译器

2.代理

1.》Jdk动态代理

2.》cglib代理

3.面向切面  


内容:

1.   使用spring的特殊bean

1》      分散配置:

使用占位符变量代替bean装配文件中的硬编码配置。占位符采用${variable}形式。

<bean id="personServiceBean" class="cn.csdn.spring.PersonServiceBean">
      <!-- 分散配置-->
<property name="name"><value>${name}</value></property>
</bean>
<!--  分散解析的处理方法-->
第一种方式:
 <bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location">
      
      </property> 
<property name="locations">
<list>
      
</list>
    </property>
 </bean>
 
第二种方法:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
   <context:property-placeholder location="person.properties"/>
</bean>
 
2.   》定制属性编译器
  <property name="homeAddress">
             <bean class="cn.csdn.spring.Address">
                 <property name="province">
                    <value>北京</value>
                 </property>
                 <property name="city">
                    <value>北京市</value>
                 </property>
                 <property name="street">
                    <value>海淀区056街道</value>
                 </property>
                 <property name="zipCode">
                    <value>111111</value>
                 </property>
            </bean>
      
      
      </property>
      <property name="comAddress">
          <value>河北省.邢台市.宁晋县.水榭花都302</value>
      
      </property>
<!-- 定制编辑器后处理类 -->
      
      <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
      <property name="customEditors">
         <map>
             <!-- key指向的是:需要转换的类 -->
             <entry key="cn.csdn.spring.Address">
                   <!-- value指向的是实现的编辑器类 -->
                  <bean class="cn.csdn.spring.AddressEditor"/>
             </entry>
         </map>
      </property>
  </bean>
//继承java.bean的类
publicclass AddressEditor extends PropertyEditorSupport{
 
    @Override
    publicvoid setAsText(String text) throws IllegalArgumentException {
       //java实现转换
       if(!"".equals(text)||text!=null){
           String arg[]=text.split("\\.");
           if(arg.length>3){
               Address address = new Address();
    
    
    
    
    
              
           }else{
              this.setAsText(null);
           }
       
           
       }else{
           
           this.setAsText(null);
       }
    }
    
    
    
}
2.代理
1.》Jdk动态代理
    package cn.csdn.srrvice;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
public class JDKProxy implements InvocationHandler{
 
     //代理的目标对象
     //private PersonServiceBean personServiceBean;
     private Object targerService;
     //根据目标对象创建代理对象
     public Object creatPoxy( Object targerService){
            
            this.targerService=targerService;
            //调用代理
            return Proxy.newProxyInstance(targerService.getClass().getClassLoader(), targerService.getClass().getInterfaces(), this);
     }
     
     /*
      * proxy 代理对象
      * methed 代理方法
      *  args   参数值
     
     
     
     @Override
     public Object invoke(Object proxy, Method method, Object[] args)
                   throws Throwable {
            // TODO Auto-generated method stub
            System.out.println("代理类的名称"+proxy.getClass().getName());
            System.out.println("方法的名称"+method.getName());
            if(args!=null&&args.length>0){
                   System.out.println("第一个参数"+args[0].toString());
                   
            }
            //执行目标代理
            Object result=method.invoke(this.targerService, args);
            
            return result;
     }
     
 
}

3.   》cglib代理
  package cn.csdn.cglib;
 
import java.lang.reflect.Method;
 
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
importnet.sf.cglib.proxy.MethodProxy;
 
 
 
 
publicclass CglibProxy  implements MethodInterceptor{
 
    
    //代理的目标对象   真实主题   角色
    private Object targetObject;
    
    // 根据目标对象创建代理对象
    public Object createPoxyInstrance(Object targetObject) {
       this.targetObject = targetObject;
       //用于创建目标对象的代理对象
       Enhancer enhancer = new Enhancer();
       enhancer.setSuperclass(this.targetObject.getClass());
       enhancer.setCallback(this);
       
       return enhancer.create(); //创建代理对象
       
 
    }
    
    @Override
    publicMethodProxythrows Throwable {
        System.out.println("代理类的名称"+proxy.getClass().getName());
        System.out.println("方法的名称"+method.getName());
        if(args!=null && args.length>0){
            System.out.println("第一个参数"+args[0].toString());
       
       
        //执行目标对象的方法
       Object result =  arg3.invoke(this.targetObject, args);
       
       return result;
    }
 
}

 
3.面向切面   
 
1》定义AOP术语
1.切面:需要实现的交叉功能
2.连接点:应用程序执行过程中插入切面的地点;此处可是方法调用,异常抛出甚至是要修改的字段
3.通知:通知切面的实际实现。它通知应用系统的行为,通知在连接点插入到应用系统中
4.切入点:定义了通知应该用在那些连接点。通常通过制定类名和方法名,或匹配类名和方法名式样的正则表达式来指定切入点。
5.引入:允许为已存在类添加新的方法和属性
6.目标对象:被通知对象,即可是编写的类也可是添加定制行为的第三方类
7.代理:将通知应用到目标对象后创建的对象
8.织入:将切面应用到目标对象从而创建一个新的代理对象的过程。切面在指定接入点被织入到目标对象中,织入发生在目标对象声明周期的多个点上:
编译器:切面在目标对象编译时织入
类装载器:切面在目标对象被载入到JVM时织入
运行期:切面在应用系统中运行时织入
9.通知包括需要应用的交叉行为:连接点是通知要在应用系统需要应用的所有切入点;切入点定义了通知要在那些连接点应用。
2》      创建通知:
Around :
接口:Org.springframework.aop.MethodInterceptor
描述:拦截对目标方法调用
Before:
接口:Org.springframework.aop.BeforeAdvice 
描述:在目标方法调用前调用
After:
接口:Org.springframework.aop.AfterReturningAdvice 
描述:在目标方法调用后调用
Throw:
接口:Org.springframework.aop.ThrowsAdvice 
描述:当目标方法抛出异常时调用
案例:
 package cn.csdn.advice;
 
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
 
public class MyAroundAdvice implements MethodInterceptor {
 
   @Override
   public Object invoke(MethodInvocation arg0) throws Throwable {
          // TODO Auto-generated method stub
          System.out.println("执行方法之前执行操作");
          
          Object obj=arg0.proceed();//执行目标方法
          System.out.println("执行方法之后执行操作");
          
return obj;
   }
 
}
package cn.csdn.advice;
 
import java.lang.reflect.Method;
 
import org.springframework.aop.AfterReturningAdvice;
 
public class MyAfterAdivce  implements AfterReturningAdvice{
 
   @Override
   public void afterReturning(Object arg0, Method arg1, Object[] arg2,
                 Object arg3) throws Throwable {
          System.out.println("after++++++++++++++++方法的返回值"+arg0);
          
   }
 
}
 
package cn.csdn.advice;
 
import java.lang.reflect.Method;
 
import org.springframework.aop.MethodBeforeAdvice;
 
public class MyBeforeAdivce implements MethodBeforeAdvice{
 
   @Override
   public void before(Method arg0, Object[] arg1, Object arg2)
                 throws Throwable {
          //第一个参数:方法多得多对象
          //第二个参数:方法的参数
          
          //第三个参数:目标对象
          
          
          Object obj=null;
          if(arg1.length>0){
                 obj=arg1[0];
                 
          }
          System.out.println("before*********方法的名称:::"+arg0.getName()+"  方法的第一个参数值"+obj.toString()+"  目标对象是:"+arg2.getClass());
}
 
}
package cn.csdn.advice;
 
import java.lang.reflect.Method;
 
import org.springframework.aop.ThrowsAdvice;
 
public class MyThrowsAdivce implements ThrowsAdvice{
   
   public void afterThrowing(Method method,Object[] args, Object target,Throwable throwable){
          
   }
}
 
 
引入通知:
/**
 * 
 *  引入通知(引入的拦截器)
 *
 */
publicclass AuditableAdvice extends DelegatingIntroductionInterceptor implements Auditable{
 
    
    private Date lastModifiedDate;
    @Override
    publicvoid setLastModifiedDate(Date lastModifiedDate) {
       this.lastModifiedDate=lastModifiedDate;
       
    }
    @Override
    public Date getLastModifiedDate() {
       returnlastModifiedDate;
    }
 
}
 
 
Beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-2.5.xsd" default-lazy-init="true">
  
  
 
 
 
   <!-- 环绕通知 -->   
   <bean id="myAroundAdvice" class="cn.csdn.advice.MyAroundAdvice"/>
   <!-- 配置前置通知 -->
   <bean id="myBeforeAdvice" class="cn.csdn.advice.MyBeforeAdivce"/>
   <!-- 配置后置通知 -->
   <bean id="myAfterAdivce" class="cn.csdn.advice.MyAfterAdivce"/>
   <!-- 配置异常通知 -->
   <bean id="myThrowsAdivce" class="cn.csdn.advice.MyThrowsAdivce"/>
   
   
    <!-- 引入通知 -->
   <bean id="auditableAdvice" class="cn.csdn.advice.AuditableAdvice"/>
   
   
   <!-- 业务bean -->
   <bean id="personServiceBean" class="cn.csdn.service.PersonServiceBean"/>
   
   <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
   
      <!-- 代理的接口 -->
      <property name="proxyInterfaces">
         <list>
           <value>cn.csdn.service.PersonService</value>
           <value>cn.csdn.advice.Auditable</value>
         </list>
      </property>
      
      <!--  通知名称-->
      <property name="interceptorNames">
         <list>
           <value>myBeforeAdvice</value>
           <value>myAroundAdvice</value>
           <value>myAfterAdivce</value>
           <value>myThrowsAdivce</value>
           <value>auditableAdvice</value>
         </list>
      </property>
      
      <!-- 通知的对象 -->
      <property name="target">
        <ref bean="personServiceBean"/>
      </property>
   
   </bean>
  
</beans>