//创建一个与代理对象相关联的InvocationHandler InvocationHandler stuHandler = new MyInvocationHandler<Person>(stu); //创建一个代理对象stuProxy,代理对象的每个执行方法都会替换执行Invocation中的invoke方法 Person stuProxy= (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);
1.2 相关知识点:Proxy
l Proxy.newProxyInstance 三个参数
n 参数1:loader ,类加载器,动态代理类运行时创建,任何类都需要类加载器将其加载到内存。
u 一般情况:当前类.class.getClassLoader();
n 参数2:Class[] interfaces 代理类需要实现的所有接口
u 方式1:目标类实例.getClass().getInterfaces();
注意:只能获得自己接口,不能获得父元素接口
u 方式2:new Class[]{UserService.class}
例如:jdbc 驱动 --> DriverManager 获得接口 Connection
n 参数3:InvocationHandler 处理类,接口,必须进行实现类,一般采用匿名内部
u 提供 invoke 方法(以下三个参数),代理类的每一个方法执行时,都将调用一次invoke
l 参数31:Object proxy :代理对象
l 参数32:Method method : 代理对象当前执行的方法的描述对象(反射)
执行方法名:method.getName()
执行方法:method.invoke(对象,实际参数)
l 参数33:Object[] args :方法实际参数
1.1 案例实现
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
HttpServletRequest requestProxy = (HttpServletRequest)Proxy.newProxyInstance(
EncodingFilter.class.getClassLoader(),
new Class[]{HttpServletRequest.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("get".equals(request.getMethod())) {
//对指定方法进行增强
if("getParameter".equals(method.getName())){
// 执行方法获得返回值
String value = (String) method.invoke(request, args);
return new String(value.getBytes("UTF-8") , "UTF-8");
}
}
//放行
return method.invoke(request, args);
}
});
//放行
chain.doFilter(requestProxy, response);
}
@Override
public void destroy() {
}
}
1.1.1 AOP相关术语
Joinpoint(连接点):
所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点。
Pointcut(切入点):
所谓切入点是指我们要对哪些Joinpoint(连接点)进行拦截的定义。
Advice(通知/增强):
所谓通知是指拦截到Joinpoint(连接点)之后所要做的事情就是通知。
通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。
Introduction(引介):
引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field。
Target(目标对象):
代理的目标对象。
Weaving(织入):
是指把增强应用到目标对象来创建新的代理对象的过程。
spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。
Proxy(代理):
一个类被AOP织入增强后,就产生一个结果代理类。
Aspect(切面):
是切入点和通知(引介)的结合。
1、使用tx标签配置的拦截器
<!--4、配置hibernate属性 --> <!--引入db.properties属性文件 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:db.properties"></property> </bean> <!-- 配置数据源,连接池使用c3p0,详细信息参见hibernate官方文档"基础配置章节" --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" dependency-check="none"> <property name="driverClass"> <value>${datasource.driverClassName}</value> </property> <property name="jdbcUrl"> <value>${datasource.url}</value> </property> <property name="user"> <value>${datasource.username}</value> </property> <property name="password"> <value>${datasource.password}</value> </property> <property name="acquireIncrement"> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 --> <value>${c3p0.acquireIncrement}</value> </property> <property name="initialPoolSize"> <!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 --> <value>${c3p0.initialPoolSize}</value> </property> <property name="minPoolSize"> <!--连接池中保留的最小连接数。 --> <value>${c3p0.minPoolSize}</value> </property> <property name="maxPoolSize"> <!--连接池中保留的最大连接数。Default: 15 --> <value>${c3p0.maxPoolSize}</value> </property> <property name="maxIdleTime"> <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 --> <value>${c3p0.maxIdleTime}</value> </property> <property name="idleConnectionTestPeriod"> <!--每60秒检查所有连接池中的空闲连接。Default: 0 --> <value>${c3p0.idleConnectionTestPeriod}</value> </property> <property name="maxStatements"> <!-- JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。 如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 --> <value>${c3p0.maxStatements}</value> </property> <property name="numHelperThreads"> <!-- C3P0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能, 通过多线程实现多个操作同时被执行。Default: 3 --> <value>${c3p0.numHelperThreads}</value> </property> </bean> <!--配置 sessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"> </property> <!-- hibernate的设置 --> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql"> ${hibernate.show_sql} </prop> <prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}</prop> <prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop> <prop key="hibernate.connection.release_mode">${hibernate.connection.release_mode}</prop> <prop key="hibernate.format_sql">${hibernate.format_sql}</prop> <prop key="hibernate.connection.SetBigStringTryClob">true</prop> </props> </property> <!-- anotation注解扫描实体类 --> <property name="packagesToScan"> <list> <value>com.pec.model</value> </list> </property> </bean> <!--5、Spring 配置声明式事物 --> <!-- 配置事务 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- 配置事务范围 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="get*" read-only="false" propagation="NOT_SUPPORTED" /> <tx:method name="find*" read-only="false" propagation="NOT_SUPPORTED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="create*" propagation="REQUIRED" /> <tx:method name="anscy*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <!-- 定义切面 --> <aop:config proxy-target-class="true"> <aop:pointcut id="pointcut" expression="execution(* com.pec.service..*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" /> </aop:config>