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">
<value>person.properties</value>
</property>
<property name="locations">
<list>
<value>person.properties</value>
</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();
address.setProvince(arg[0]);
address.setCity(arg[1]);
address.setStreet(arg[2]);
address.setZipCode(arg[3]);
setValue(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 参数值
* (non-Javadoc)
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
*/
@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;
import net.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
public Object intercept(Object proxy, Method method, Object[] args,MethodProxy arg3) throws 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){
System.out.println("exception----------------------------"+throwable.getMessage());
}
}
引入通知:
/**
*
* 引入通知(引入的拦截器)
*
*/
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>