spring课堂笔录_1001

来源:互联网 发布:淘宝联盟订单查询 编辑:程序博客网 时间:2024/05/21 08:51
1 什么是spring ?
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架.
spring的设计思想是,单例模式和工厂模式
2 spring的四大特点(优点)


轻量级,低侵入的设计
Spring的DI机制降低了业务对象替换的复杂性
spring不依赖于web容器,独立于各种应用服务器, Write Once,Run Anywhere(一次编译到处运行)
高度开放性:Spring并不完全依赖于Spring,开发者可自由选用Spring框架的部分或全部,它的架构仍然是内在稳定的


3   spring的组成部分 七大模块


    Spring Core:Spring的基石,提供了Spring的最主要的核心机制:控制反转和依赖注入
    Spring Context:提供了Spring的上下文信息,如:国际化,验证等
    
    Spring Web支持:简化了处理多部分请求
    Spring MVC框架支持:一个全功能的构建 Web 应用程序的 MVC 实现,MVC 容纳了大量视图技术,其中包括 JSP、Velocity等。
    
    Spring Dao支持:Spring的Dao支持大大的简化了JDBC操作数据库所带来的繁琐
    Spring ORM支持 pring框架集成了若干ORM框架,从而提供了ORM的对象关系工具,其中包括 JDO、Hibernate、iBatis和TopLink。
                   所有这些都遵从Spring的通用事务和DAO异常层结构。


    Spring AOP:面向方面编程,提供了事务,日志,权限,安全等处理机制




具体解释
Spring 核心容器(Core):提供Spring框架的基本功能。核心容器的主要组件是BeanFactory,它


是工厂模式的实现。BeanFactory使用控制反转(Ioc)模式将应用程序的配置和依赖性规范与实际的应


用代码程序分开。


Spring AOP:通过配置管理特性,Spring AOP模块直接面向方面的编程功能集成到了Spring框架中,所以可以很容易的使Spring框架管理的任何对象支持 AOP。Spring AOP模块为基于Spring的应用程序


中的对象提供了事务管理服务。通过使用Spring AOP,不用依赖于EJB组件,就可以将声明性事务管理


集成到应用程序中。


Spring ORM:Spring框架集成了若干ORM框架,从而提供了ORM的对象关系工具,其中包括 JDO、Hibernate、iBatis和TopLink。所有这些都遵从Spring的通用事务和DAO异常层结构。


Spring DAO:JDBC DAO抽象层提供了有意义的异常层次的结构,可用该结构来管理异常处理和不同数据供应商抛出的异常错误信息。异常层次结构简化了错误处理,并且大大的降低 了需要编写的异常代码数量(例如,打开和关系连接)。Spring DAO的面向JDBC的异常遵从通用的DAO异常层结构。


Spring WEB:Web上下文模块建立在上下文模块(Context)的基础之上,为基于Web服务的应用


程序提供了上下文的服务。所以Spring框架支持 Jakarta Struts的集成。Web模块还简化了处理多部分请求


及将请求参数绑定到域对象的工作


Spring上下文(Context):Spring上下文是一个配置文件,向Spring框架提供上下文信息。


Spring上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化校验和调度功能。


Spring MVC:Spring的MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,


MVC框架变成为高度可配置的,MVC容纳的大量视图技术,包括JSP、Velocity、Tiles、iText和Pol




4 spring的核心机制 


    1).控制反转(IoC/Inverse Of Control):调用者不再创建被调用者的实例,由spring框架实现(容器创建)所以称为控制反转。
    2).依赖注入(DI/Dependence injection) :容器创建好实例后再注入调用者称为依赖注入。

当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,
在传统的程序设计过程中,通常由调用者来创建被调用者的实例, 但在Spring里,创建被调用者的工
作不再由调用者来完成,因此称为控制反转; 创建被调用者 实例的工作通常由Spring容器来完成,
然后注入调用者,因此也称为依赖注入




   什么是ioc容器
mn
    bean工厂(BeanFactory) 和 应用上下文(Application Context)




在Spring中,BeanFactory是IoC容器的核心接口。 它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
                      BeanFactory
  |
  |
                  ApplicationContext(国际化,事件)
          /              \
 /                \
FileSystemXmlApplicationContext     ClassPathXmlApplicationContext


 
 常用有三种方式可以得到BeanFactory ,从而获得bean实例,并进行调用


  //        InputStream is = new FileInputStream("beans.xml");
// InputStreamResource isr = new InputStreamResource(is);
// BeanFactory beanFactory = new XmlBeanFactory(isr);
//    
//     Spring给出一些BeanFactory的实现类,其中最为常用的是XmlBeanFactory。
//     1、通过文件系统
//     Resource res = new FileSystemResource("src/beans.xml");
//     XmlBeanFactory beanFactory = new XmlBeanFactory(res);
//     2、通过类路径(class路径 ./表示上级目录)  
//     ClassPathResource res = new ClassPathResource("./beans.xml");
//     XmlBeanFactory beanFactory = new XmlBeanFactory(res);
//     3、通过ApplicationContext加载(ClassPathXmlApplicationContext或者FileSystemXmlApplicationContext)
//     ApplicationContext appContext = new ClassPathXmlApplicationContext(
//     new String[] {"./beans.xml"});
//     BeanFactory beanFactory = (BeanFactory) appContext;
//
//        ClassPathResource res = new ClassPathResource("./beans.xml");
// XmlBeanFactory beanFactory = new XmlBeanFactory(res);




         或者 ApplicationContext ctx=new FileSystemXmlApplicationContext("src/bean.xml");
        
ApplicationContext增加功能 1国际化2事件支持
 
 国际化测试
             (1)bean配置
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
                 <property name="basenames">
            <list>
                <value>message</value>
<!-- 如果有多个资源文件,全部列在此处-->
            </list>
        </property>
          </bean>
(2)
    ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");
String[] a = {"读者"};
String hello = ctx.getMessage("hello",a,Locale.ENGLISH);//英文
Object[] b = {new Date()};
String now = ctx.getMessage("hello",b,Locale.getDefault());//默认
System.out.println(hello);
System.out.println(now);
  
         


5  简单测试BeanFactory


   <?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">


<beans>
<bean id="aaa" class="包名.类名"/>
</beans>


   测试  FileSystemXmlApplicationContext默认从项目目录寻找bean配置文件xml
 ApplicationContext ctx = new FileSystemXmlApplicationContext("src/bean.xml");
   Test t=(Test)ctx.getBean("aaa");
 System.out.println(t.getName());
 
  依赖注入的优点,代码将更加清晰,Spring管理bean的灵巧性, bean与bean之间的依赖关系放在配置文件里组织,
  不再担心对象之间的依赖关系之后,实现更高层次的松耦合将易如反掌
  
  
  依赖注入的方式 (为什么叫依赖注入 类的四种关系  )  
    (1)set注入(2)构造注入(3)lookup方法注入




    setter注入实例
  <bean id="aaa" class="包名.类名">
<property name="属性名">
<ref local="另一个bean id"/>//local与bean的区别
</property>
    </bean>


 
 //local与bean的区别  local:当前xml   bean:整个spring容器 所走加载的xml文件搜索




  构造注入实例 提供构造方法(注入的实例参数)  要提供无参的构造方法
  <bean id="aaa" class="包名.类名">
<constructor-arg><ref bean="steelAxe"/></constructor-arg>
    </bean>


  (3)lookup方法注入(依赖注入的bean每次都创建一个新实例)
    这种方法主要是用在Singleton的Object中使用非Singleton的Bean时,
    通过lookup-method的那个方法来取得非Singleton的Bean。一般用的不多,在用这种定义之前最佳想明白你的需求。 
    
    1 Singleton的Object 中提供一个抽象方法,返回非Singleton的Bean,此时Singleton的类变成抽象类 如
      public abstract class Test//Singleton的Bean {
TestBean tb;//非Singleton的Bean时
 
public TestBean getTb() {
return tb;
}


public void setTb(TestBean tb) {
this.tb = tb;
}


public abstract TestBean  createXxx();
      }
    2  配置xml
         <bean id="testbean" class="com.TestBean"  singleton="false"/>//注意singleton="false"
   <bean id="test" class="com.Test">
    <property name="tb"> <ref local="testbean"/></property>//注意这个依然不能少
    <lookup-method name="createXxx" bean="testbean"/>
       </bean>
   3 测试
         Test t=(Test)ctx.getBean("test");
System.out.println("不使用lookup-method注入");
TestBean tb1=t.getTb();
TestBean tb2=t.getTb();
System.out.println(tb1==tb2);
System.out.println("使用lookup-method注入");
TestBean  tb3=t.createXxx();
TestBean  tb4=t.createXxx();
System.out.println(tb3==tb4);


结果
    不使用lookup-method注入
true
使用lookup-method注入
false






注入其他属性例子
    <beans>


<bean id="aaa" class="包名.类名"/>


<bean id="bbb" class="lee.Chinese">
<property name="schools">
            <list>
                <value>小学</value>
                <value>中学</value>
                <value>大学</value>
            </list>
</property>




<property name="score">
            <map>
                <entry key="数学">
                    <value>87</value>
                </entry>
                <entry key="英语">
                    <value>89</value>
                </entry>
                <entry key="语文">
                    <value>82</value>
                </entry>
            </map>
</property>




        <property name="health">
            <props>
                <prop key="血压">正常</prop>
                <prop key="身高">175</prop>
            </props>
        </property>




        <property name="axes">
            <set>
                <value>xxx</value>
                <bean class="包名.类名"/>
                <ref local="另外一个bean id"/>
            </set>
        </property>
    </bean>
</beans>


上述中的health指的是Properties属性类
private Properties health = new Properties();






     








  测试  Spring的DI机制降低了业务对象替换的复杂性  面向接口编程的好处  灵活配置


6  spring  bean的实例 创建的几种方式
       (1)构造器   单例思想
       (2)静态工厂(静态方法创建)


         静态方法名(iint type)


       <bean id="xxx" class="包名.类名(工厂类)" factory-method="静态方法名">
        <constructor-arg value="1"></constructor-arg>
</bean>




创建同一接口下不同实例


     (3)工厂方法(非静态方法创建)
           <bean id="aaa" class="包名.类名(工厂类)">
            <property name="type"><value>1</value></property>
           </bean>


       <bean id="xxx" factory-bean="工厂bean id(如刚刚的aaa) " factory-method="非静态方法名">


7  自动装配


   


       有两个bean A与B
       B作为A的一个属性,当我们没有通过setter注入或者构造注入B实例时,我们可以在A bean中指定autowire属性,
       让它在spring容器个根据不同方式自动寻找b实例




自动装配的优缺点:


优点:自动装配能显著减少配置的数量,自动装配可以使配置与java代码同步更新


缺点:Spring会尽量避免在装配不明确的时候进行猜测,容器中可能存在多个bean定义跟自动装配的


setter方法和构造器参数类型匹配




     
    byName(用于set注入) 根据属性名自动装配。此选项将检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配。例如,在bean定义中将autowire设置为by name,而该bean包含master属性(同时提供setMaster(..)方法),Spring就会查找名为master的bean定义,并用它来装配给master属性。
 
    byType 如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配。如果存在多个该类型的bean,那么将会抛出异常,并指出不能使用byType方式进行自动装配。若没有找到相匹配的bean,则什么事都不发生,属性也不会被设置。如果你不希望这样,那么可以通过设置dependency-check="objects"让Spring抛出异常。
 
   constructor 与byType的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
 
   autodetect 通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式。
 
  


   在用byType时候,如果没有匹配的bean 可测试dependency-check="objects"让Spring抛出异常




 8  spring框架中bean的生命周期?


  (1)  bean定义


    在配置文件里面用<bean></bean>来进行定义。


  (2)  bean初始化


    有两种方式初始化:  也可同时使用。参数指定的后执行


         A.在配置文件中通过指定init-method属性来完成


         B.实现org.springframwork.beans.factory.InitializingBean接口  实现afterPropertiesSet()方法


  (3)  bean调用


    有三种方式可以得到bean实例,并进行调用,前面有所讲述


  (4)  bean销毁


    销毁有两种方式。也可同时使用  参数指定的销毁方法后运行


         A.使用配置文件指定的destroy-method属性


         B.实现org.springframwork.bean.factory.DisposableBean接口 实现destroy()方法
            
   可以通过调用ConfigurableListableBeanFactory(XmlBeanFactory)里的destroySingletons销毁单例对象,测试destroy()方


  ConfigurableListableBeanFactory beanFactory = 
new XmlBeanFactory(new FileSystemResource("src/bean.xml"));
    beanFactory.destroySingletons();
           }
    
     是的, 当调用beanFactory.destroySingletons()方法的时候,bean不会马上销毁,但是容器在销毁bean之前,会等到方法结束剩余的任务后
     再调用相应的销毁bean之前指定的其他方法。再干掉bean




  在 spring 2.5中 ((AbstractApplicationContext)beanFactory).registerShutdownHook();来看看bean的销毁


     原型 bean 在创建后即脱离 BeanFactory 的维护,所以只能调用初始化方法,而不能做清理工作。 
 如果不是Singleton的Bean不能触发结束初始化事件和预销毁事件么?那是因为如果不是单例模式的Bean,Spring不会自己去管理,而是把它们交给Spring框架下的应用本身去管理,这样就相当于把Bean交给了GC。但是如果是单例模式的Bean,Spring会建立一个Bean的列表来统一管理,在Spring应用被关闭的时候,会执行BeanFactory中的destroySingltons()方法来逐个销毁列表中的Bean。这就是为什么只有单例模式实现Spring的那两个事件接口或指定方法属性才是有效的






      可以考虑引入bean的后处理技术






   9 spring 中bean的作用域(5种):2.0或者以前只有单例和非单例   2。0以后有以下5种


singleton


在每个Spring IoC容器中一个bean定义对应一个对象实例。


prototype


一个bean定义对应多个对象实例。


request


在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各自的bean实例, 它们依


据某个bean定义创建而成。该作用 域仅在基于web的Spring ApplicationContext情形下有效。


session


在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring


ApplicationContext情形下有效。


global session


在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet


context的时候有效。该作用域仅在基于 web的Spring ApplicationContext情形下有效。


10  spring在web环境中的配置(2种)


1.在Web.xml中配置上下文载入器


根据你的系统情况,你可以选择两种上下文载入器:ContextLoaderListener和ContextLoaderServlet.
如果你的Web容器支持Servlet2.3标准或更高,你可以使用两者,否则只能使用后者.


(1)ContextLoaderListener在Web.xml应该如下配置:
<listener> 
    <listener-class>
 org.springframework.web.con.ConttextextLoaderListener
    </listener-class> 
</listener> 
(2)ContextLoaderServlet在Web.xml应该如下配置:
<servlet>
 <servlet-name>context</servlet-name>
 <servlet-class>
 org.springframework.web.context.ContextLoaderServlet
 </servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet>


2.指定上下文载入器的配置文件
不论你使用的那种上下文载入器,你都应该指明Spring配置文件的位置.如果没有指定,上下文载入器将把/web-inf/applicationContext.xml当作Spring配置文件。
要指定Spring配置文件的位置,你可以在Servlet上下文设置contextConfigLocation参数来为上下文载入器指定一个或多个Spring配置文件
(使用通配符或是用逗号隔开)。如下所示:
 <context-param>
   <param-name>
contextConfigLocation
  </param-name>
  <param-value>
 /WEB-INF/bean.xml
  </param-value>
</context-param>


3.获得应用上下文
接下来我们就可以获得ApplicationContext了,代码如下:
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext); 
在一个自启动的Servlet中,我们可以这样获得它:
public class InitialSystemServlet extends HttpServlet {
 public void init(ServletConfig config) throws ServletException {
   // 取得Spring的上下文
   WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(config.getServletContext());


 }






     

                               测试web应用环境相关的Bean作用域


       spring 2.5 dtd配置




      <?xml version="1.0" encoding="UTF-8" ?>
  <beans xmlns="http://www.springframework.org/schema/beans"
   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">


<bean id="test" class="com.Test" >
</bean>
     </beans>




如果用户使用spring的webApplicationContext,则可以使用另外3种Bean的作用域:request,session和globalSession.不过
在使用这些作用域之前,首先必须在web容器中进行一些额外的配置,在高版本的web容器中,则可以利用HTTP请求监听器进行配置:


<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>

细心的同学可能有一个疑问:在介绍webApplicationContext初始化时,我们已经通过ContextLoaderListener将web容器与
spring容器整合,为什么这里又要引入一个额外的RequestContextListener以支持Bean的另外3个作用域呢?
在整合spring容器时使用ContextLoaderListener,它实现了ServletContextListener监听器接口,ServletContextListener
只负责监听web容器启动和关闭的事件.而RequestContextListener实现ServletRequestListener监听器接口,该监听器监听
HTTP请求事件,web服务器接收的每一次请求都会通知该监听器.
spring容器启动和关闭操作由web容器的启动和关闭事件触发,但如果spring容器中的Bean需要request,session,globalsession
作用域的支持,spring容器本身就必须获得web容器的HTTP请求事件,以HTTP请求的事件"驱动"Bean作用域的控制逻辑.




11 spring 对dao的支持
    <1>dao模式优点
        减少开发代码量 提高工作效率
        降低系统资源消耗 提高系统性能
        业务逻辑层与持久层(数据层)的分离,使数据与操作更为清晰。
        数据访问独立到了一层,修改具体实现类,不影响系统的架构运行
     <2>DAO模式的四个组件
        DAO接口
        DAO接口实现类
        pojo值对象
        DAO实例的定位(工厂 或 spring注入)
    


    2. 核心类  
       JdbcTemplate(需要注入DataSource) 
       JdbcDaoSupport类(简化注入,有一个字段dataSource)
       并提供了getJdbcTemplate()方法获得JdbcTemplate实例
       
       DataSource接口
为了从数据库中取得数据,我们首先需要获取一个数据库连接。Spring通过DataSource对象来完成这个工作。
DataSource是JDBC规范的一部分,它被视为一个通用的数据库连接工厂。通过使用DataSource, 
Container或Framework可以将连接池以及事务管理的细节从应用代码中分离出来。 
作为一个开发人员,在开发和测试产品的过程中,你可能需要知道连接数据库的细节。
但在产品实施时,你不需要知道这些细节。通常数据库管理员会帮你设置好数据源。 
在使用Spring JDBC时,你既可以通过JNDI获得数据源,也可以自行配置数据源(使用Spring提供的DataSource实现类)。
使用后者可以更方便的脱离Web容器来进行单元测试。 这里我们将使用DriverManagerDataSource
,不过DataSource有多种实现, 后面我们会讲到。使用DriverManagerDataSource和你以前获取一个JDBC连接 的做法没什么两样。
你首先必须指定JDBC驱动程序的全限定名,这样DriverManager 才能加载JDBC驱动类,接着你必须提供一个url(因JDBC驱动而异,
为了保证设置正确请参考相关JDBC驱动的文档), 最后你必须提供一个用户连接数据库的用户名和密码。

目前已经有开源的免费用了
                            DataSource
  /          \
 /            \
     DriverManagerDataSource(spring的实现)           org.apache.commons.dbcp.BasicDataSource





下面我们将通过一个例子来说明如何配置一个 DataSource ,
 
 
       
      1 自己实现DataSource接口,设置数据库相关连接信息


       
      2 使用现有的实现类dataSource  编程方式 获得dataSourc 如下


DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/j2ee");
dataSource.setUsername("root");
dataSource.setPassword("123456");


     3 spring方式


      <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
        <property name="url"><value>jdbc:mysql://localhost:3306/j2ee</value></property>
        <property name="username"><value>root</value></property>
        <property name="password"><value>123456</value></property>
       </bean>




 通过开源dbcp获得dataSource ,


<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/j2ee</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>123456</value>
</property>
</bean>








    




    使用Spring的Dao支持来写Dao层,继承JdbcDaoSupport类,JdbcDaoSupport类中有一个字段dataSource
    也就是数据库连接,因此只需继承JdbcDaoSupport类,并给它注入dataSource,就隐式的获得了数据库连接,可以在bean.xml文件中
    注入connection(即:dataSource)
     <beans>
     <!-- spring 方式获得dataSource-->

      <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
        <property name="url"><value>jdbc:mysql://localhost:3306/j2ee</value></property>
        <property name="username"><value>root</value></property>
        <property name="password"><value>123456</value></property>
       </bean>


<bean id="xxx" class="包名.类名(dao的实现类)">
<property name="dataSource">
<ref local="dataSource"/>
</property>
</bean>


     </beans>




    3.在这个Dao 实现类中写一个内部类,使其实现:RowMapper接口,用来封装成具体的pojo对象,代码如下


private class PersonRowMapper implements RowMapper
{
public Object mapRow(ResultSet resultSet, int rowNumber)
throws SQLException {
User user = new User();
user.setId(resultSet.getLong("id"));
user.setName(resultSet.getString("name"));
user.setSex(resultSet.getString("sex"));
user.setAge(resultSet.getInt("age"));
user.setAddr(resultSet.getString("addr"));
return user;
 }
}




     4 通过JdbcTemplate类进行增删查询修改操作
         (1)增加 修改 删除示例
     public void createPerson(PersonBean p)
       {
Object[] args = {p.getName() , new Integer(p.getAge()) };
getJdbcTemplate().update("insert into person_test(p_name,p_age) values(?,?)", args );
       }
          (2)查询 返回单个object
       public PersonBean getPerson(int id)
       {
Object[] args = {new Integer(id)};
//PersonRowMapper是刚刚的内部类
return (PersonBean)getJdbcTemplate().queryForObject("select p_name,p_age from person_test where p_id = ?", args, new PersonRowMapper());
        }
  (3)返回list
     public List findPersonsByName(String name)
     {
       //PersonRowMapper是刚刚的内部类
return getJdbcTemplate().query("select * from person_test where p_name like '%" + name +"%'" , new PersonRowMapper());
     }




    5 spring 2.5以后提供了一个SimpleJdbcTemplate类来操作
           2.5例子
 
      public class PersonDaoSpring25 implements PersonDao {


private SimpleJdbcTemplate simpleJdbcTemplate;


public void setDataSource(DataSource dataSource) {
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
}


@Override
public void add(Person p) {
// TODO Auto-generated method stub


String sql = "insert into  person(name) values(?)";
simpleJdbcTemplate.update(sql, p.getName());
}


@Override
public void del(String id) {
// TODO Auto-generated method stub
String sql="delete from person where id=?";
simpleJdbcTemplate.update(sql, id);
}


@Override
public List findAll() {
// TODO Auto-generated method stub
String sql = "select * from person";


List list = simpleJdbcTemplate.getJdbcOperations().query(sql,
new BeanPropertyRowMapper(Person.class));


return list;


}


@Override
public Person findById(String id) {
String sql = "select * from person where id=?";


Person p = simpleJdbcTemplate.queryForObject(sql,
ParameterizedBeanPropertyRowMapper.newInstance(Person.class),
id);


return p;


}


@Override
public void update(Person p) {
String sql = "update person set name=? where s_id=?";


simpleJdbcTemplate.update(sql, p.getName(), p.getId());


}


}




12   spring  aop    (  三种代理    五种处理   3个advisor<掌握正则>   )


       


AOP的好处:
消除了编码模块之间的依赖
可以在任意阶段,向已有功能模块中填加新功能,且不侵入原有功能


AOP的特征:


       各步骤之间的良好隔离性 , 源代码的无关性


 
  Spring 面向方面编程(AOP) spring支持AOP功能,AspectJ更完美的支持AOP


 AOP 的核心构造是方面,它将那些影响多个类的行为封装到可重用的模块中, 将系统中通用的需求功能隔离出来形成一个功能模块,
 并将这个模块切入到应用程序当中, AOP追求的是调用者与被调用者的解耦,从而消除了OOP引起的代码混乱和分散问题,
  增强了系统的可维护性和代码的重用性
  
  方面:哪方面 系统中分为业务方面的和非业务方面  Spring主要集中于非业务方面 如(日志、事务、安全、权限等)


  1.面向方面与面向切面:AOP的实现中的几个重要的概念:
        1.1如果理解为“面向方面编程”:
            针对于某一模块进行专门的编写(如:面向日志编程,面向事务编程,面向权限等),其意思就是说面向具体的某个功能模块来编程,然后将其切入到项目中
        1.2如果理解为“面向切面编程”:
           
            连接点:程序执行过程中明确的点,如方法的调用或者异常的抛出,举个例子,如果是一个权限系统的话,要控制到类中的某一个具体的方法,那么这个方法就是一个连接点
            切入点:连接点的集合,如类中多个个方法的调用, 还是以权限系统来举例,如果要控制一个类中的多个方法的话,那么这几个方法(也即是几个连接点)组成了一个切入点
            切面:如果要控制多个类中的多个方法,那么这多个类就组成了一个切面
   连接点 --- 切入点 ---- 切面(三者之间的关系可以形象的理解为:点--线--面)
   引入(Introduction):添加方法或字段到被通知的类。Spring允许引入新的接口到任何被通知的对象。例如,
       你可以使用一个引入使任何对象实现IsModified接口,来简化缓存。
          
            AOP实现过程中的几种不同的方式: 
       拦截一类中所有的方法(连接点)
       拦截一个类中的某些符合条件的方法(切入点)
       拦截多个类中的符合条件的方法(切面)




        2.1.连接点 --- 切入点 ---- 切面 --- 方面(解决方案的切入点)
        2.2.目标对象(也就是:寻找被处理的类)
        2.3.AOP代理(具体实现),分为二种,
            2.3.1  JDK动态代理(面向接口)
              1、创建一个实现java.lang.reflect.InvocationHandler 接口的代理类,如:


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;


public class PerformanceHandler implements InvocationHandler{
   private Object target; //要进行代理的业务类的实例
   public PerformanceHandler(Object target){
this.target = target;
   }
//覆盖java.lang.reflect.InvocationHandler的方法invoke()进行织入(增强)的操作
   public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable{
System.out.println("Object target proxy:"+target);
System.out.println("模拟代理加强的方法...");
Object obj = method.invoke(target, args); //调用目标业务类的方法
System.out.println("模拟代理加强的方法执行完毕...");
return obj;
   }
}


2、用java.lang.reflect.Proxy.newProxyInstance()方法创建动态实例来调用代理实例的方法:


import java.lang.reflect.Proxy;


public class Test{
   public static void main(String args[]){
接口 xxx = new 真实实现类名(); // 在这里指定被代理类
InvocationHandler ds = new DynamicSubject(xxx); // 初始化代理类  用代理类把目标业务类进行编织
接口  接口变量= (接口) Proxy.newProxyInstance(xxx.getClass().getClassLoader(), xxx.getClass().getInterfaces(), ds);////创建代理实例,它可以看作是要代理的目标业务类的加多了横切代码(方法)的一个子类


                       接口变量.方法//调用方法


   }
}




                  /**
* 从以上可以看出,动态代理可以任意指定被代理的类,即真实对象类,而代理模式则无法实现该功能,
* 因为他把真实对象的写死在代理类里,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是
* 实际使用时,一个真实角色或其接口必须对应一个代理角色,如果大量使用会导致类的急剧膨胀
*/






              2.3.2 Cglib代理(面向具体类)  




             1、创建一个实现net.sf.cglib.proxy.MethodInterceptor接口的实例来为目标业务类加入进行代理时要进行的操作或增强:


import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
/**
*CGlib采用非常底层的字节码技术,可以为一个类创建子类,
并在子类中采用方法拦截技术拦截父类方法的调用,并顺势进行增强,即是织入横切逻辑
* @author zxl
*/
public class CglibProxy implements MethodInterceptor{
   private Enhancer enhancer = new Enhancer();
   //覆盖MethodInterceptor接口的getProxy()方法,设置
   public Object getProxy(Class clazz){
enhancer.setSuperclass(clazz); //设者要创建子类的类
enhancer.setCallback(this); //设置回调的对象
return enhancer.create(); //通过字节码技术动态创建子类实例,
   }


   public Object intercept(Object obj,Method method,Object[] args,
   MethodProxy proxy) throws Throwable {
System.out.println("方法执行前加入功能1");


//通过代理类实例调用父类的方法,即是目标业务类方法的调用
Object result = proxy.invokeSuper(obj, args);
System.out.println("方法执行后加入功能1");
return result;
   }
}


2、通过java.lang.reflect.Proxy的getProxy()动态生成目标业务类的子类,即是代理类,再由此得到代理实例:




import java.lang.reflect.Proxy;


public class TestCglibProxy {
   public static void main(String args[]){
CglibProxy proxy = new CglibProxy();


//动态生成子类的方法创建代理类
目标类名 fsi =
(目标类名)proxy.getProxy(目标类名.class);


、//调用业务方法
   }
}




















        2.4.处理(Spring AOP处理)或者叫通知,aop框架在特定的连接点执行的动作,Spring提供了五种处理方式
2.5 Advisor=(处理+切入点)
2.6 下面介绍Spring的处理 
   实现步骤
      (1)目标对象定义 bean定义
       (2) 处理(通知)与Advisor  处理也称作通知  在使用任何pointcut切入点实现之前,你首先必须创建一个Advisor
    <1> 处理 定义(1 在哪里处理<连接点 --- 切入点 ---- 切面 --- 方面> 2什么方式处理<如前处理,后处理,前后都处理>)
                         如果只是简单的定义处理,则默认的切入点是目标类的所有方法都处理


    <2>  如果希望更精确的切入点,则建议采用Advisor(切入点+处理)
         spring Advisor 体系
   Advisor
      |
      |
-----------------
      |                 |
      |                 |
PointcutAdvisor    IntroductionAdvistor
                                                                       |
      |
                                  -----------------------------------------------------------
                                                   |                   |                                     |
  |                   |                                     |
              DefaultPointcutAdvisor    NameMatchMethodPointcutAdvisor         RegexpMethodPointcutAdvisor 








<2.1>  以下是采用正则表达式支持类RegexpMethodPointcutAdvisor的示例
 
 配置Advisor  (Advisor=切入点+通知)


<bean id="testAdvisor"
  class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!--  advice属性确定处理bean-->
<property name="advice">
<!-- 此处的处理bean定义采用嵌套bean,也可引用容器的另一个bean-->
<bean class="包名.通知bean类名" />
</property>
<!--  patterns确定正则表达式模式-->
<property name="patterns">
<list>
<!--  确定正则表达式列表-->
<value>.*say.*</value> <!-- 业务实现方法名匹配 -->
</list>
</property>
</bean>
                       
<2.2>  NameMatchMethodPointcutAdvisor

<bean id="testAdvisor"
  class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<!--  advice属性确定处理bean-->
<property name="advice">
<!-- 此处的处理bean定义采用嵌套bean,也可引用容器的另一个bean-->
<bean class="包名.通知bean类名" />
</property>
<!--  mappedName确定匹配模式-->
<property name="mappedName" value="hello*" />
                                       
<!--如果匹配多个  mappedNames确定匹配模式-->
                                        <property name="mappedNames">
<list>
<value>arrayStr1</value>
<value>arrayStr2</value>
<value>arrayStr2</value>
</list>
</property>


</bean>
      






<2.2>  DefaultPointcutAdvisor示例


                            Spring2中除了NameMatchMethodPointcutAdvisor和RegexMethodPointcutAdvisor提供了对一定命名规则和正则表达式切入点的封装,
       defaultPointcutAdvisor则提供了一切切入点的支持,Spring提供了4种用来定义切入的类,分别为:
org.springframework.aop.support.NameMatchMethodPointcut、
org.springframework.aop.support.JdkRegexpMethodPointcut、
org.springframework.aop.support.Perl5RegexpMethodPointcut,
org.springframework.aop.support.ExpressionPointcut,
  这四种可以用来描述切入点的类均可由DefaultPointcutAdvisor来进行封装,首先我们讲解一下DefaultPointcutAdvisor的使用方法:
  DefaultPointcutAdvisor类的使用很简单,他有一个 advice及 pointcut 属性,advice属性用来指明要使用的通知,pointcut属性用来指定切入点,我们可以通过构造子或设值注入方式来配置这个 Bean。
  看下面的构造子注入方式: 如下
  
      <bean id="defaultAdvisor"       class="org.springframework.aop.support.DefaultPointcutAdvisor">
      <property name="advice" ref=" 通知类id "/>
      <property name="pointcut" ref="pointcutBean" />
  </bean>
                            
   面集合这四种切入点的描述类一起讲解DefaultPointcutAdvisor:
                              <2.2.1>、org.springframework.aop.support.NameMatchMethodPointcut
    
  <bean id="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
   <property name="mappedNames"> 
   <list> 
    <value>business*</value> 
     </list> 
  </property> 
 </bean>
  
                               <2.2.2>  org.springframework.aop.support.JdkRegexpMethodPointcut
<bean id="pointcutBean"
 class="org.springframework.aop.support. JdkRegexpMethodPointcut">
   <property name="pattern"> 
<value>.*business.*</value> 
     </property> 
    <property name="ExcludedPattern"> 
<value>business2</value> 
     </property>
</bean>
                                <2.2.3> org.springframework.aop.support.Perl5RegexpMethodPointcut
                                       <bean id="pointcutBean"
class="org.springframework.aop.support. Perl5RegexpMethodPointcut">
   <property name="pattern"> 
<value>.*business.*</value> 
     </property> 
    <property name="ExcludedPattern"> 
<value>business2</value> 
     </property>
    </bean>
                                <2.2.4> org.springframework.aop.support.ExpressionPointcut


                                    <bean id="pointcutBean" 
class="org.springframework.aop.aspectj.AspectJExpressionPointcut">
<property name="expression" 
   value="execution(void spring.chapter3.proxy.Component.business*(..))"> 
  </property> 
  </bean>








<2.2.5> 自定义切入点


1、编写Advisor实现类


在此可直接使用org.springframework.aop.support.DefaultPointcutAdvisor


2、编写Advice实现类
public class PlayAdvice implements MethodBeforeAdvice{
public void before(Method method, Object[] args, Object target)
  throws Throwable {
 System.out.println("my before advice");
// method.invoke(target, args); 如果再调用这句,则目标方法会执行多一次
}
}


3、编写Pointcut实现类
public class PlayPointcut implements Pointcut {
public ClassFilter getClassFilter() {
 return new PlayClassFilter();
}
public MethodMatcher getMethodMatcher() {
 return new PlayMethodMatcher();
}
}
//PlayClassFilter的定义


class PlayClassFilter implements ClassFilter {
public boolean matches(Class clazz) {
 if(clazz.getSimpleName().equals("Play"))
  return true;
 return false;
}
}


//PlayMethodMatcher的定义


class PlayMethodMatcher implements MethodMatcher {
public boolean isRuntime() {
 return true;
}
public boolean matches(Method method, Class c) {
 if(c.getSimpleName().equals("Play")&&method.getName().contains("Service"))
  return true;
 return false;
}
public boolean matches(Method method, Class c, Object[] args) {
 if(c.getSimpleName().equals("Play")&&method.getName().contains("Service"))
  return true;
 return false;
}
}


4、编写目标类


public class Play {


 public void playService(String what){
 System.out.println("play "+what);
}
}




5、在配置文件中配置




<bean id="adviceBean" class="com.PlayAdvice"/>
<bean id="pointcutBean" class="com.PlayPointcut"/>
<bean id="playService" class="com.Play"/>
<bean
  class="org.springframework.aop.support.DefaultPointcutAdvisor">
  <property name="advice" ref="adviceBean"></property>
  <property name="pointcut" ref="pointcutBean"></property>
</bean>
                                           
                                       
    
                     




(3) aop代理对象定义 bean 定义    spring生成代理技术
    <0>手写aop代理(编程式)
   
            <1>采用ProxyFactoryBean生成代理
         特点:一种接口或者一个类 都需要对应的一个具体代理,需要指定接口或者类 以及对应的代理定义


    <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--当用面向具体类实现时  proxyInterfaces属性可以不用注入 此时采用Cglib代理,必须加入Cglib的jar包 -->
<property name="proxyInterfaces">
<value>包名.目标对象的接口</value>
</property> 


<property name="target">
<ref local="目标对象的bean id"/>
</property>
<property name="interceptorNames">
<list>
<value>处理bean id</value><!-- list说明可以注入多个处理 -->
</list>
</property>
  </bean>
   
   <2> 自动代理  主要采用了 bean的后处理技术 实现了bean的后处理接口BeanPostProcessor,通常有两个常用的实现类
                      在spring bean 的生命周期中,可以在bean创建之后(如指定init-method),销毁之前(指定distory-method),让容器
     执行特定的方法,如果有更多的方法,需要在创建之时(注意是创建之时)被调用,可采用实现BeanPostProcessor接口
                         
 
使用BeanPostProcessor,让我们的bean实现BeanPostProcessor接口
 1     public class Chinese  implements Person,BeanPostProcessor{
@Override
public void sayHello() {
// TODO Auto-generated method stub
System.out.println("你好");
}


@Override
public Object postProcessAfterInitialization(Object arg0, String arg1)
throws BeansException {
// TODO Auto-generated method stub
System.out.println("进入postProcessAfterInitialization方法");
System.out.println(arg1);//返回之前可以包装一下
return arg0;
}
@Override
public Object postProcessBeforeInitialization(Object arg0, String arg1)
throws BeansException {
// TODO Auto-generated method stub
System.out.println("进入postProcessBeforeInitialization方法");
System.out.println(arg1);//返回之前可以包装一下
return arg0;
}
}
                                  
   2 客户端调用
                                        
Resource res = new FileSystemResource("src/beans.xml");
   XmlBeanFactory beanFactory = new XmlBeanFactory(res);
Chinese c = new Chinese();
beanFactory.addBeanPostProcessor(c);//注意这句哦,注册BeanPostProcessor
Person p = (Person)beanFactory.getBean("chinese");




                           
                        spring为我们提供了以下两种实现


  BeanPostProcessor
    /           \
   /             \
 BeanNameAutoProxyCreator       DefaultAdvisorAutoProxyCreator
   
   <2.1>  采用BeanNameAutoProxyCreator自动生成代理   
       特点:多种接口或者多个类 自动创建其对应代理,需要指定接口或者类。接口或者类共用一个自动代理


      <!-- 定义BeanNameAutoProxyCreator-->
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!--  指定对满足哪些bean name的bean自动生成业务代理 -->
   <property name="beanNames">
   <!--  下面是所有需要自动创建代理的bean-->
   <list>
<value>bean id 1</value>
<value>bean id 2</value>
   </list>
   </property>
<!--  下面定义BeanNameAutoProxyCreator所需的处理-->
<property name="interceptorNames">
   <list>
<value>处理 bean 1</value> 
<value>处理 bean 2</value> 
   </list>
</property>
   </bean>
                    
   
   <2.2> 更牛的自动代理DefaultAdvisorAutoProxyCreator, 面向接口
        特点:多种接口或者多个类 自动创建其对应代理,不需要指定接口或者类,提供Advisor(切入点+通知),默认搜索所有的Advisor 如前面的正则表达式
       <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>




        (1).before advice(前置通知)   implements MethodBeforeAdvice  重写before()方法
           是在目标bean方法调用前调用,没有返回值,通常意外情况下,会继续运行下一步方法.记住的一点是没有返回  
             例子如下
    public class MyBeforeAdvisor implements MethodBeforeAdvice
{
 
   public void before(Method m, Object[] args, Object target) throws Throwable
{
System.out.println("方法调用之前...");
System.out.println("下面是方法调用的信息:");
System.out.println("所执行的方法是:" + m);
System.out.println("调用方法的参数是:" + args);
System.out.println("目标对象是:" + target);
System.out.println("方法调用之前111...");
   }
}
   


(2).after advice(后置通知)   implements  AfterReturningAdvice 重写afterReturning()方法
是在方法调用后调用,有返回值,记住的一点是有返回值。
   public void afterReturning(Object returnValue, Method m, Object[] args, Object target)throws Throwable
  {
System.out.println("方法调用结束...");
System.out.println("目标方法的返回值是 : " + returnValue);
System.out.println("目标方法是 : " + m);
System.out.println("目标方法的参数是 : " + args);
System.out.println("目标对象是 : " + target);


           }
(3).around advice(环绕通知)  implements MethodInterceptor 重写其内的invoke()方法,实现方式与Struts2的拦截器一模一样
    调用其 MethodInvocation 的proceed()方法;
            例子如下
     public class MyAroundInterceptor implements MethodInterceptor
{
 
   public Object invoke(MethodInvocation invocation) throws Throwable
{

System.out.println("调用生小孩方法之前娶老婆: invocation对象:[" + invocation + "]");
Object rval = invocation.proceed();
System.out.println("调用方法之后...坐月子");
return rval;
   }
}
 


(4).throws advice(异常通知)  implements ThrowsAdvice
  例子如下
    public class MyExceptionAdvice implements ThrowsAdvice
{
   public void afterThrowing(ClassNotFoundException ex) throws Throwable
   {
System.out.println("系统抛出ClassNotFoundException异常,异常提示为: " + ex.getMessage());
   }
 
   public void afterThrowing(Method m,Object[] o,Object target,Throwable e)throws Throwable{
  System.out.println("消息:"+e.getMessage());
}


   public void afterThrowing(Method m, Object[] args, Object target, ArithmeticException ex)
   {
System.out.println("系统抛出ArithmeticException异常,异常提示为: " + ex.getMessage());
System.out.println("抛出异常的方法为: " + m);
System.out.println("抛出异常的方法的参数为: " + args);
System.out.println("抛出异常的目标对象为: " + target);
   }


 
}




(5).introduce advice(引入通知)  理解引入通知是干什么的
引入通知是一种特殊的通知,它能将新的成员变量、成员方法引入到目标类中,引入新的接口。它不能作用于任何切入点,
因为它只作用于类层次,而不是方法层次。实现引入通知需要实现IntroductionAdvisor和IntroductionInterceptor接口。
引入通知不能调用proceed方法。Advisor必须针对每个实例,并且是有状态的。
引入通知的效果类似于设计模式中的访问者模式(Visitor Pattern)

示例:为目标对象加锁 即当目标对象企图修改某个属性值时,无法修改
   <1>extends DefaultIntroductionAdvisor,因为DefaultIntroductionAdvisor,因为实现IntroductionAdvisor实现IntroductionAdvisor
   
        public class LockMixinAdvisor extends DefaultIntroductionAdvisor

   public LockMixinAdvisor()
{
super(new LockMixin(), Lockable.class);//Lockable是我们要引入的接口。LockMixin是它的实现类
   }
}
             <2>extends DelegatingIntroductionInterceptor,因为DelegatingIntroductionInterceptor实现了IntroductionInterceptor接口
                   public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable

   private boolean locked; 
   public void lock()
{
this.locked = true;
   } 
   public void unlock()
{
this.locked = false;
   } 
   public boolean locked()
{
return this.locked;
   } 
   public Object invoke(MethodInvocation invocation) throws Throwable 
{
if (locked() && invocation.getMethod().getName().indexOf("set") == 0)
   throw new Exception("属性加锁,无法修改");
return super.invoke(invocation);
   } 
}
        
//   Lockable接口
   public interface Lockable
{
   void lock();
   void unlock();
   boolean locked();
}


                《3》客户端调用 示例
ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");
Person p = (Person)ctx.getBean("person");
p.run();
p.setAge(56);
p.run();
Lockable lp = (Lockable)p;//注意这里的强转,表明引入成功
lp.lock();
p.setAge(23);
p.run();






     3.spring 对aspectj的支持  基于Schema的AOP支持      更细粒度的控制      需要aspectjweaver.jar支持 
         相应dtd
 
<?xml version="1.0" encoding="UTF-8"?>
   <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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   
  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:aspectj-autoproxy />  <!-- 启动aspectj支持-->
      
      <aop:config>
<aop:aspect id="asp" ref="拦截的处理bean id <如包含前置通知,后置通知,环绕通知等>">
<aop:pointcut id="mycut"
expression="execution(* com.*.*(..))" />
<!-- pointcut-ref :切入点引用-->

       <aop:before pointcut-ref="mycut" method="before处理方法名" />
<aop:after-returning pointcut-ref="mycut"
method="后置处理方法名" returning="返回参数名" />
<aop:after-throwing pointcut-ref="mycut" method="异常处理方法名"
throwing="异常处理方法参数名" />
<aop:after pointcut-ref="mycut" method="最终通知方法名" />
<aop:around pointcut-ref="mycut" method="环绕通知方法名" />


      </aop:aspect>
               </aop:config>
      
    </beans>    




          切面代码实例
     public class MyInterceptor {


private void anyMethod() {
}// 声明一个切入点


public void doAccessCheck() {
System.out.println("前置通知:" );
}


public void doAfterReturning(int result) {
System.out.println("后置通知:" );
}


public void doAfterThrowing(Exception e) {
System.out.println("例外通知:" + e);
}

public void doAfter() {
System.out.println("最终通知");
}


public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// if(){//判断用户是否在权限
System.out.println("进入方法");
Object result = pjp.proceed();// 当使用环绕通知时,这个方法必须调用,否则拦截到的方法就不会再执行了
System.out.println("退出方法");
// }
return result;
}


          }




    Spring AOP 用户可能会经常使用 execution切入点指示符。执行表达式的格式如下:


     execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
          throws-pattern?)


     execution(修饰符? 返回类型  包名。类名?  方法名(参数)异常抛出?)


       下面给出一些通用切入点表达式的例子。


任意公共方法的执行:
execution(public * *(..))


任何一个名字以“set”开始的方法的执行:
execution(* set*(..))


AccountService 接口定义的任意方法的执行:
execution(* com.xyz.service.AccountService.*(..))


在service包中定义的任意方法的执行:
execution(* com.xyz.service.*.*(..))


在service包或其子包中定义的任意方法的执行:
execution(* com.xyz.service..*.*(..))


如果只拦截返回方法为String类型的,表达式应为:: 
execution(java.lang.String com.xyz.service..*.*(..))


如果只拦截第一个输入参数为String类型的方法,表达式应为:: 
execution(* com.xyz.service..*.*(java.lang.String,..))


如果只拦截非void返回类型的方法,表达式应为:: 
execution(!void  com.xyz.service..*.*(..))








   


     4 利用aop进行事务编程  Spring事务配置的五种方式 (掌握Spring事务体系图)
   
   传统上,J2EE开发者有两个事务管理的选择: 全局 或 本地事务(局部事务)。全局事务由应用服务器管理,使用JTA。
   局部事务是和资源相关的,比如一个和JDBC连接关联的事务
    
      事务种类分为: jdbc事务(局部事务) jta事务(全局事务) 容器事务


1、JDBC事务控制的局限性在一个数据库连接内,但是其使用简单。局部事务


2、JTA事务的功能强大,事务可以跨越多个数据库或多个DAO,使用也比较复杂。全局事务


3、容器事务,主要指的是J2EE应用服务器提供的事务管理,局限于EJB应用


   两种事务的比较 
             1、JDBC事务控制的局限性在一个数据库连接内,但是其使用简单。


             2、JTA事务的功能强大,事务可以跨越多个数据库或多个DAO,使用也比较复杂  


 






   从实现的角度划分


  Spring把事务分为两种一种是:编程式事务,一种是声明式事务。
  编程式事务是侵入式事务 比较灵活,编程式事务则要操作逻辑代码。存在重复的代码比较多,相对繁琐,而且不利于系统的扩展;
  声明式事务是非侵入式的事务。声明式事务只需在配置文件中配置,而不需要去操作逻辑代码。


  spring事务的7大传播属性


    1.PROPAGATION_MANDATORY:要求调用该方法的线程必须处于事务环境中,否则抛出异常。
    2.PROPAGATION_NESTED:如果执行该方法的线程已处于事务环境下,依然启动新的事务,方法在嵌套的事务里执行。
      如果执行该方法的线程并未处于事务中,也启动新的事务,然后执行该方法,此时与PROPAGATION_REQUIRED相同。
    3.PROPAGATION_NEVER:不允许调用该方法的线程处于事务环境下,如果调用该方法的线程处于事务环境下,则抛出异常。
    4.PEOPAGATION_NOT_SUPPORTED:如果调用该方法的线程处于在事务中,则先暂停当前事务,然后执行该方法。
    5.PEOPAGATION_REQUIRED:要求在事务环境中执行该方法,如果当前执行线程已处于事务中,则直接调用,
    如果当前执行线程不已处于事务中,则启动新的事务后执行该方法。
    6.PEOPAGATION_REQUIRES_NEW:该方法要求有一个在新的事务环境中执行,如果当前执行线程已处于事务中,
    先暂停当前事务,启动新的事务后执行该方法;如果当前执行线程不已处于事务中,则启动新的事务后执行该方法。
    7.PEOPAGATION_SUPPORTS:如果当前执行线程已处于事务中,则使用当前事务,否则不使用事务。






         Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部 
DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,
TransactionManager的实现为HibernateTransactionManager。根据代理机制的不同,总结了五种Spring事务的配置方式
          现在以dataSource为例,当然要先配置dataSource,参见去前面文档spring方式获得dataSource部分
 <1> 每个bean有一个代理
     
      <1.1>配置事务管理器transactionManager
    
       <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                   <!-- 给DataSourceTransactionManager注入dataSource-->
 <property name="dataSource"><ref local="dataSource"/></property>
                 </bean>
               <1.2>配置事务代理bean    TransactionProxyFactoryBean
<bean id="xxx"  
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">  
  <!-- 配置事务管理器  引用上面配置的来注入 -->  
  <property name="transactionManager" ref="transactionManager" />     
  <property name="target" ref="操作数据库的目标 dao bean id" />  
<!-- 配置事务属性 -->  
<property name="transactionAttributes">  
   <props>  
<prop key="*">PROPAGATION_REQUIRED</prop>
   </props>  
</property>  
   </bean>  


         <2>  所有Bean共享一个代理基类   实则上就是spring 的模板机制  配置一个模板,使其为abstract="true"
                 spring中bean 的继承 在java 类中称为继承 在spring称为模板
           


    <2.1>代理定义 定义模板(父类)
     
     <bean id="baseTxProxy" lazy-init="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> 
<property name="transactionManager"><ref bean="transactionManager"/></property> 
<property name="transactionAttributes"> 
   <props> 
<prop key="*">PROPAGATION_REQUIRED</prop> 
   </props> 
     </property> 
    </bean> 


     <2.2> 为不同的dao操作类加上事务
   <!-- 给dao1加事务-->
 <bean id="daotran1" parent="baseTxProxy">     <!-- baseTxProxy为刚刚配置的模板-->
<property name="target"> 
   <ref local="dao1"/> 
</property> 
   </bean> 
 
   <!-- 给dao2加事务-->
 <bean id="daotran2" parent="baseTxProxy"> 
<property name="target"> 
   <ref local="dao2"/> 
</property> 
   </bean> 



<!--  原来的两步骤-->
<bean id="personDaoSpring25" class="com.PersonDaoImplSpring25">
<property name="dataSource"><ref local="springdataSource"/></property>
</bean>




<bean id="personDaoSpring25Tran" parent="parent">
<property name="target"><ref local="personDaoSpring25"/></property>
</bean>


 
<!--  原来的两步骤 变作一步-->


<bean id="personDaoSpring25One"  parent="parent">
 <property name="target">
 <bean class="com.PersonDaoImplSpring25">
  <property name="dataSource"> <ref local="springdataSource"/></property>
 </bean>
 </property>
</bean>


 
           <3>使用拦截器
     <3.1>定义事务拦截器  org.springframework.transaction.interceptor.TransactionInterceptor
    <bean id="transactionInterceptor"  
class="org.springframework.transaction.interceptor.TransactionInterceptor">  
<!-- 配置事务管理器  引用上面配置的来注入 -->  
<property name="transactionManager" ref="transactionManager" />  
<!-- 配置事务属性 -->  
<property name="transactionAttributes">  
   <props>  
<prop key="*">PROPAGATION_REQUIRED</prop>  
   </props>  
</property>  
   </bean>
               <3.2> 定义代理 bean 采用自动代理 BeanNameAutoProxyCreator (前面讲过有例子)
                     <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">  
<property name="beanNames">  
   <list>  
<value>*dao</value> <!--  dao bean id匹配  --> 
   </list>  
</property>  
<property name="interceptorNames">  
   <list>  
<value>transactionInterceptor</value>  <!--  引用事务拦截器  -->
   </list>  
</property>  
                   </bean>  




         <4> 使用tx标签配置的拦截器  基于Schema的AOP支持
             <?xml version="1.0" encoding="UTF-8"?>
   <beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xmlns:tx="http://www.springframework.org/schema/tx"
   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
  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">








      <tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
   <tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
               </tx:advice>


<aop:config>


<aop:pointcut   id="interceptorPointCuts"
   expression="execution(* com.*.*(..))"   />
<aop:advisor advice-ref="txAdvice"
   pointcut-ref="interceptorPointCuts" />     
     
</aop:config>   


          <5> 使用注解 
      配置文件加上
        
<context:annotation-config />  <!--  启用注解支持  -->
                 <context:component-scan base-package="com" /><!--  要扫描的com包  -->
<tx:annotation-driven transaction-manager="transactionManager"/> <!--  使用tx标签引入事务管理器  -->
              
      需要事务的类加上@Transactional注解
               






13  spring与struts的整合    




     整合中要思考的是:怎样才能加载和实例化spring容器.先把spring容器放到web容器中,然后再根据一些方法去提取,
     
     
     13.1  在Strust1中直接使用spring
     
     让我们回顾一下前面所讲的如何在web环境中使用spring,
     根据servlet版本的不用,我们可以通过在web.xml里配置servlet或者监听器来实例化spring容器,
      
        1.在web.xml中配置 
①.加载spring 容器 
<!-- 加载spring 容器 --> 
<context-param> 
 <param-name>contextConfigLocation</param-name> 
 <param-value>/WEB-INF/classes/beans.xml</param-value> 
</context-param> 
②.实例化spring 容器 
<!-- 初始化spring容器方法一  servlet版本 前面有讲述--> 
<servlet> 
<servlet-name>contextLoader</servlet-name> 
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> 
<load-on-startup>0</load-on-startup> 
</servlet> 
<!-- 初始化spring容器方法二   监听器版 前面有讲述--> 
<listener> 
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 
     
     
     之后就可以通过WebApplicationContextUtils取得Spring的上下文


   WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(当前ServletContext);
  
   如在struts1中,必须知道当前的servlet上下文
             ①WebApplicationContext ctx=WebApplicationContextUtils.getWebApplicationContext(this.servlet.getServletContext());
    //这种获得servlet上下文在以下整合的后两种方式中会呗空指针错误,所以采用request.getSession().getServletContext()获得servlet上下文。如
    ②WebApplicationContext beanFactory=WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
           
  如在struts2中
   WebApplicationContext ctx=WebApplicationContextUtils.getWebApplicationContext();
 


   有了WebApplicationContext实例,我们就可以通过getBean方法获得spring容器中的bean了,如下所示
                    ctx.getBean("id名")
       


      
      13.2  Strust1整合Spring的其他3种方式
               
        在上面的Strust1中直接使用Spring,我们是通过在web.xml中配置servlet或者是listener加载和实例化spring容器。实则上
 spring提供了一种专门针对于struts1的插件来加载和实例化spring容器,只需在struts-config.xml加入即可,
 其他3种整合方式中可采用以下插件配置替代在web环境中的监听器或者servlet
                     
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/classes/applicationContext.xml" />
</plug-in>


                          <!-- 
 注意 /WEB-INF/classes/applicationContext.xml这个位置,如果你的文件在WEB-INF。则写成/WEB-INF/applicationContext.xml
 在eclipse 中 /WEB-INF/classes/applicationContext.xml对应的目录是src目录,applicationContext.xml放在src下
 -->


                  ◆使用Spring的ActionSupport类整合Structs
     优点: 
1)  简单 
     缺点: 
1)  耦合高  它将Struts动作与Spring框架耦合在一起。如果您想替换掉Spring,那么您必须重写代码
2)  违反IOC 
3)  无法使用 DispatchAction 
 ◆使用Spring的DelegatingRequestProcessor覆盖Struts1的RequestProcessor
    DelegatingRequestProcessor方法的确比第一种方法好,缺点 RequestProcessor如果改变了怎么办或者是有不同的RequestProcessor怎么办呢
 ◆将Struts Action管理委托给Spring框架
动作委托解决方法是这三种方法中最好的。Struts动作不了解Spring,不对代码作任何改变就可用于非Spring应用程序中。RequestProcessor的改变不会影响它,并且它可以利用Spring AOP特性的优点。
                     优点 
1.  动作委托解决方法是这三种方法中最好的。 
2.  不使用Spring api编写  Action 
3.  利用了IOC装配 




   三种方式的相关配置:
  
   <1> Action直接继承ActionSupport,在Action类的execute()方法中通过
ApplicationContext ctx=getWebApplicationContext()获得Spring的
上下文,通过上下文获取相应的bean实例
      
   <2>覆盖RequestProcessor
1.在struts-config.xml中配置控制器


<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
2.在applicationContext.xml文件中注册action动作bean


<bean name="/struts-config.xml配置的对应action的path" class="Action类的包名类名" > 
<!--注意上面的是name而不是大家经常写的id-->
<property name="service">
<ref bean="service" />  <!--注入spring实例,假设属性名为service-->
</property>
</bean>
3.Action类中声明一个Service私有属性及其setter方法,通过IOC注入Service实例。
      
   <3>动作管理委托给Spring
1.struts-config.xml中action标签内的type属性值替换为org.springframework.web.struts.DelegatingActionProxy,如下
 
<action input="/index.jsp" path="/hello" scope="session"
  type="org.springframework.web.struts.DelegatingActionProxy">
<forward name="success" path="/success.jsp" />
</action>


2.在applicationContext.xml文件中注册action动作bean


<bean name="/struts-config.xml配置的对应action的path" class="Action类的包名.类名" >
<property name="service">
<ref bean="service" />
</property>
</bean>
3.Action类中声明一个Service私有属性及其setter方法,通过IOC注入Service实例






  13.2  Spring与Struts2的整合
       由于Struts2得强大可插拔式设计,使得整合spring的工作变得异常简单,struts2-spring-plugin-2.0.8.jar就是支持spring的插件包
         


            0.把struts2支持spring的插件包jar拷贝到项目中
          
   1.web.xml的配置:


 <?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


<!-- 监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


<!-- 定义Struts2的FilterDispathcer的Filter -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>


<!-- FilterDispatcher用来初始化struts2并且处理所有的WEB请求。 -->
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>


    2.applicationContext.xml的配置(WEB-INF目录下)
        (如果不使用默认的 则可以在web.xml通过以下配置修改xml的配置以及名称)
 <!-- 加载spring 容器 --> 
<context-param> 
 <param-name>contextConfigLocation</param-name> 
 <param-value>/WEB-INF/classes/beans.xml</param-value> 
</context-param> 
     
      






 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">


<bean name="service" class="com.service.impl.ServiceImpl"/>


<!-- action的配置 -->
<bean name="abc" class="com.LoginAction" >
<property name="service">
<ref bean="service" /> <!--注入spring实例,假设action类中有一个属性名为service-->
</property>
</bean>
</beans>


    3.struts.xml的配置


 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<include file="struts-default.xml" />
<package name="default" extends="struts-default">
<!-- action标签中的class属性与applicationContext.xml中的action的bean的name属性一致 如以下的abc -->
<action name="login" class="abc">
<result name="input" >/login.jsp</result>
<result name="success">/welcome.jsp</result>
<result name="error">/failed.jsp</result>
</action>
</package>
</struts>


    4.action类中声明service的一个变量及setter方法


    spring.xml:
    <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">


<beans>
<bean id="beanDao" class="dao.impl.BeanDaoImpl">
</bean>
<bean id="beanService" class="service.impl.BeanServiceImpl">
<property name="dao" ref="beanDao"></property>
</bean>
<bean id="beanAction" class="web.BeanAction">
<property name="service" ref="beanService"></property>
</bean>
</beans>


struts.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<include file="struts-default.xml" />
<package name="struts" extends="struts-default" >
<action name="bean_*" class="beanAction" method="{1}">
<result name="success">/success.jsp</result>
<result name="info">/info.jsp</result>
</action>
</package>
</struts>


web.xml:


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>S2S</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
 classpath:spring.xml
  </param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>








       
14  Spring2.5有哪些改进




Spring2.5rc1发布了,一直想知道它葫芦里卖什么药
0 spring对dao的支持2.5的simpleJdbcTemplate与2.0的JdbcTemplate
1 spring   bean的作用域 已经有原来的单例和非单例 变成了5个
        2 Jar 包:一个包分解成多个包 如 SpringMVC 不再使用spring.jar 这个庞大的包了。 Spring-webmvc.jar, spring-webmvc-portlet.jar 可以在 lib/modules 目录下找到,而且对于Struts1.* 的支持的包也应该改成 spring-webmvc-struts.jar了。
3   Hibernate:注意Spring已经不再支持Hibernate 3.1之前的版本了,也就是说2.1,3.0的版本也无法使用了。如果仍然要用的话,推荐使用Spring的2.0.6/2.0.7版本。
4. JDK版本: JDK至少要1.4.2以上,如果仍然打算使用1.3的话就请用2.0.6/2.0.7版本吧。
5. XML配置:推荐使用XML metadata格式,不过先前的DTD仍然支持。需要注意的一点是,Spring2.0的DTD继续使用“singleton”属性,但是新的Spring2.5 DTD不允许使用“singleton”属性了,改成“scope”属性来描述bean的生命周期。
6. 废弃的类与方法:有些在先前版本标注过“@deprecated”的类与方法已经完全被废弃了。
比如:


  1.
     ResultReader : 被 RowMapper 接口取代。
  2.
     BeanFactoryBootstrap : 考虑使用 BeanFactoryLocator 或自定义的bootstrap类来代替。


7. Apache OJB:注意Spring源代码中已经完全把这个去掉了,但与之整合的类仍然可以在Spring Modules project找到。https://springmodules.dev.java.net/
8. iBATIS:注意Spring已经不再支持iBATIS 的1.3版本了, 如果想继续的话,请升级到2.3以上吧。
9. JDO:注意Spring已经不支持JDO1.0了。同样,你可以升级到2.0以上版本,或者使用Spring的2.0.6/2.0.7版本。
10. UrlFilenameViewController:这个东东我也没有接触过,这里,我就简单翻译一下吧。
“考虑到嵌套路径的请求,视图名称现在决定叫UrlFilenameViewController了,这是一个突破性的改变,并且意味着如果你从Spring1.* 升级到Spring2.0 你可以使用该类从而减少Spring Web MVC的配置工作。”


15 spring 注解


     <一> 1  @Autowired 按照类型进行装配  2   @Autowired               
                                              @Qualifier("bean名称")
          
   需要<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>   
     <二> JSR-250 的注释   
    @Resource  不用于构造注入         有2个属性name与type   默认 byName 自动注入 
      
      使用示例   @Resource(type=Chinese.class)  @Resource(name="chinese") 




    @PostConstruct 
    @PreDestroy
           加入common-annotations.jar包
           需要<bean  class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>




     可用 <context:annotation-config/>。简化第一和第二的配置 请看下面的配置:


   <?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    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:annotation-config/> 


<bean id="chinese" class="com.Chinese"></bean>
<bean id="American" class="com.American"></bean>
<bean id="test" class="com.Test"></bean>


</beans>


     <三>  @Component
         
 Component或者@Component("bean名")    @Component默认bean名为类名  首字母小写
          不需要配置bean  配置文件如下
                           <?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   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:component-scan base-package="com"/>   <!--com包  这里改成你的包名-->
</beans>
 


    <四> 采用具有特殊语义的注释


Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository、@Service 和 @Controller。
在目前的 Spring 版本中,这 3 个注释和 @Component 是等效的,但是从注释类的命名上,很容易看出这 3 个注释分别和持久层、
业务层和控制层(Web 层)相对应。
虽然目前这 3 个注释和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。
所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用 @Repository、@Service 和 @Controller
对分层中的类进行注释,而用 @Component 对那些比较中立的类进行注释。


    <五> @AspectJ注解  @Aspect  @Pointcut  @Before     
           
        1 @Pointcut  @Before 分开


   //定义切入点
@Aspect
 public class SampleAspect {
     @Pointcut("execution(* com..*.*(..))")
     public void inServiceLayer() {
 System.out.println("33333333333");
     }
 }
     


            //处理类(通知类) 
    @Aspect
public class SampleAdvice {
@Before("com.SampleAspect.inServiceLayer()")
public void logInfo() {
System.out.println("=====================================");
System.out.println("Aop: do before in service layer");
System.out.println("=====================================");
}
}




 2 @Pointcut  @Before 结合用
 
//①通过该注解将PreGreetingAspect标识为一个切面 
@Aspect 
public class PreGreetingAspect{ 
// ②定义切点和增强类型 
@Before("execution(* greetTo(..))") 
public void beforeGreeting()
{
//③增强的横切逻辑 
System.out.println("How are you");






        


                    以下是具体说明  高手可掠过
       






    Spring 通过一个 BeanPostProcessor 对 注解进行解析,所以要让 注解 起作用必须事先在 Spring 容器中声明 AutowiredAnnotationBeanPostProcessor Bean。
  
   
   如下
     <!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 -->


   <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>


   15.1    Spring 2.5 引入了 @Autowired 注解,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作,按照类型进行装配
          如
             @Autowired
public void setP(Person p) {
this.p = p;
}




    15.2   当不存在不匹配的bean或者是匹配的bean的数目大于1时,按照类型进行装配都会报出异常,可采用以下方式不报都会报出异常
               @Autowired(required = false)   




    15.3    采用以下方式指定bean,按名字匹配
             @Autowired
             @Qualifier("bean名称")


    用在构造方法上
      @Autowired
public Test(@Qualifier("chinese")Person p) {
// TODO Auto-generated constructor stub
this.p=p;
}








15.3 使用 JSR-250 的注释   @Resource   @PostConstruct 和 @PreDestroy




            Spring 不但支持自己定义的 @Autowired 的注释,还支持几个由 JSR-250 规范定义的注释,它们分别是 @Resource、@PostConstruct 以及 @PreDestroy。
            
   为了让 JSR-250 的注释生效,除了在 Bean 类中标注这些注释外,还需要在 Spring 容器中注册一个负责处理这些注释的 BeanPostProcessor:


            <bean  class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>




   @Resource


@Resource 的作用相当于 @Autowired,只不过 @Autowired 按 byType 自动注入,而 @Resource 默认按 byName 自动注入罢了。@Resource 有两个属性是比较重要的,分别是 name 和 type,Spring 将 @Resource 注释的 name 属性解析为 Bean 的名字,而 type 属性则解析为 Bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略。
Resource 注释类位于 Spring 发布包的 lib/j2ee/common-annotations.jar 类包中,因此在使用之前必须将其加入到项目的类库中。


            
        JSR-250 为初始化之后/销毁之前方法的指定定义了两个注释类,分别是 @PostConstruct 和 @PreDestroy,这两个注释只能应用于方法上。标注了 @PostConstruct 注释的方法将在类实例化后调用,而标注了 @PreDestroy 的方法将在类销毁之前调用。




        使用 <context:annotation-config/> 简化配置
  而我们前面所介绍的 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor 就是处理这些注释元数据的处理器。但是直接在 Spring 配置文件中定义这些 Bean 显得比较笨拙。Spring 为我们提供了一种方便的注册这些 BeanPostProcessor 的方式,这就是 
  
  <context:annotation-config/>。请看下面的配置:


   <?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    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:annotation-config/> 


<bean id="chinese" class="com.Chinese"></bean>
<bean id="American" class="com.American"></bean>
<bean id="test" class="com.Test"></bean>


</beans>
 


         <context:annotationconfig/> 将隐式地向 Spring 容器注册 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor 以及 equiredAnnotationBeanPostProcessor 这 4 个 BeanPostProcessor。




    15.4 使用 @Component或者@Component("bean名")    @Component默认bean名为类名  首字母小写


                然我们可以通过 @Autowired 或 @Resource 在 Bean 类中使用自动注入功能,但是 Bean 还是在 XML 文件中通过 <bean> 进行定义 —— 也就是说,在 XML 配置文件中定义 Bean,通过 @Autowired 或 @Resource 为 Bean 的成员变量、方法入参或构造函数入参提供自动注入的功能。能否也通过注释定义 Bean,从 XML 配置文件中完全移除 Bean 定义的配置呢?答案是肯定的,我们通过 Spring 2.5 提供的 @Component 注释就可以达到这个目标了。

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   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:component-scan base-package="com"/><!--com包-->
</beans>
 


 
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 保温饭盒里有气打不开怎么办 保温饭盒摔了一下打不开怎么办 饭盒跟盖子盖一起打不开怎么办 玻璃杯子盖被水吸住打不开怎么办 电饭煲热剩饭没加水怎么办 微波炉碗盖子吸住了怎么办 微波炉转饭盖子吸住了怎么办 玻璃碗放进微波炉打不开怎么办 乐扣微波炉加热后打不开怎么办 美的微波炉盖子打不开怎么办 美的微波炉门都打不开了怎么办 饭煮好了有异味怎么办 一正常吃饭就胖怎么办 高铁盒饭没15的怎么办 上火车前票丢了怎么办 减肥期吃了汉堡怎么办 寿司店鳗鱼有刺怎么办 吃泡面胃难受该怎么办 吃上火的东西脸上长痘痘怎么办 减肥期间吃撑了怎么办 喝了变质的牛奶怎么办 绿豆糕吃多了会怎么办 小孩抓米饭烫了手怎么办 减肥不来月经了怎么办 吃了馊了的米饭怎么办 饭在冰箱里硬了怎么办 剩米饭反潮了怎么办 吃馊米饭中毒后怎么办? 蒸熟的米饭发黄怎么办 孕妇肉类吃的少怎么办 大米饭坏了吃了怎么办 米饭煮糊了锅怎么办 减肥吃了猪肉脯怎么办 吃了硬米饭胃痛怎么办 宝宝吃了硬物怎么办 米饭卡在喉咙里了怎么办 喉咙里卡了米饭怎么办 孕妇吃了坏鹅蛋怎么办 1岁大宝宝长短腿怎么办 行测中的判断推理怎么办 塑料盖子玻璃罐头瓶子打不开怎么办