面试题:AOP面向切面编程

//创建一个与代理对象相关联的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>

 

posted @ 2018-05-22 21:09  阿善9  阅读(1064)  评论(0编辑  收藏  举报