关于Spring的一些笔记

1 Spring是什么?

不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器(在 Spring 框架中是 IOC 容器) 负责将这些联系在一起。在典型的 IOC 场景中,容器创建了所有对象,并设置必要的属性将它们连接在一起,决定什么时间调用方法。

具体步骤有:

1、编写业务对象 UserDao UserService

2、配置ApplicationContext.xml

3、实例化Spring IOC

4、通过IOC使用Spring加工过的业务对象

 

以一个实例说明:

1 package com.aop2;
2 
3 public interface IMessage {
4     public void check();
5 }
 1 package com.aop2;
 2 
 3 public class Message implements IMessage {
 4 
 5     private String name;
 6 
 7     public String getName() {
 8         return name;
 9     }
10 
11     public void setName(String name) {
12         this.name = name;
13     }
14 
15     public void check() {
16         System.out.println("checking " + name);
17     }
18 
19 }

配置beans.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 4     xmlns:p="http://www.springframework.org/schema/p"
 5     xsi:schemaLocation="http://www.springframework.org/schema/beans 
 6     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
 7 
 8     <bean id = "message" class = "com.aop2.Message">
 9         <property name = "name" value = "alvin"/>
10     </bean>
11 
12 </beans>

添加测试类:

 1 package com.aop2;
 2 
 3 import org.junit.Test;
 4 import org.springframework.context.ApplicationContext;
 5 import org.springframework.context.support.ClassPathXmlApplicationContext;
 6 
 7 public class AopTest {
 8     @Test
 9     public void test() {
10         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
11                 "com/aop2/beans.xml");
12         IMessage message1 = (IMessage)applicationContext.getBean("message");
13         message1.check();
14     }
15 }

输出:checking alvin

 

2 通过代理实现

上述过程并没有使用代理机制,下面使用Spring的动态代理机制实现:

更改配置类:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 4     xmlns:p="http://www.springframework.org/schema/p"
 5     xsi:schemaLocation="http://www.springframework.org/schema/beans 
 6     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
 7 
 8     <!-- 配置被代理对象 -->
 9     <bean id = "message" class = "com.aop2.Message">
10         <property name = "name" value = "alvin"/>
11     </bean>
12     
13     <!-- 配置代理对象 -->
14     <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
15         <!-- 代理接口集 -->
16         <property name="proxyInterfaces">
17             <list>
18                 <value>com.aop2.IMessage</value>
19             </list>
20         </property>
21         
22         <!-- 配置被代理对象 -->
23         <property name="target" ref="message" />
24     </bean>
25 
26 </beans>

修改测试类:

package com.aop2;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AopTest {
    @Test
    public void test() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                "com/aop2/beans.xml");
        IMessage message1 = (IMessage)applicationContext.getBean("proxyFactoryBean");
        message1.check();
    }
}

测试结果:checking alvin

可以看到,测试结果并没有改变,但是我们在beans.xml配置中把被代理对象message利用IOC机制放入代理对象,实现了控制的反转,在测试类中,我们将不再直接取出message类,而是通过调用动态代理类proxyFactoryBean来调用类,并取得类方法。这就揭示了Spring的思想——解耦。它是的类与类之间的耦合度降低,我们不再类中直接调用相应的方法,而是通过bean容器配置,设置必要属性的方法来使用。

 

3 调用多个接口

增加接口:

1 package com.aop2;
2 
3 public interface IMessage2 {
4     public void release();
5 }

添加property:

1 <property name="proxyInterfaces">
2     <list>
3         <value>com.aop2.IMessage</value>
4         <value>com.aop2.IMessage2</value>
5     </list>
6 </property>

测试类:

 1 package com.aop2;
 2 
 3 import org.junit.Test;
 4 import org.springframework.context.ApplicationContext;
 5 import org.springframework.context.support.ClassPathXmlApplicationContext;
 6 
 7 public class AopTest {
 8     @Test
 9     public void test() {
10         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
11                 "com/aop2/beans.xml");
12         IMessage message1 = (IMessage)applicationContext.getBean("proxyFactoryBean");
13         IMessage2 message2 = (IMessage2)applicationContext.getBean("proxyFactoryBean");
14         message1.check();
15         message2.release();
16     }
17 }

测试结果为:

checking alvin
release alvin

 

4 AOP

AOP是在动态代理的基础上实现的,利用InvocationHandler动态代理接口产生一个对象的代理对象,对被代理对象进行代理,以下是动态代理的实质:

 1 public class DaiLi_DongTai {
 2     public static void main(String[] args) {
 3         IGamePlayer player = new GamePlayer("张三");
 4         InvocationHandler handler = new GamePlayIG(player);
 5         System.out.println("开始时间:" + new Date());
 6         ClassLoader cl = player.getClass().getClassLoader();
 7         IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(cl,
 8                 new Class[] { IGamePlayer.class }, handler);
 9         proxy.login("zhagnsan", "password");
10         proxy.killBoss();
11         proxy.upgrade();
12         System.out.println("结束时间:" + new Date());
13     }
14 }
15 
16 class GamePlayIG implements InvocationHandler {
17     Class cls = null; //被代理者
18     Object obj = null; //被代理的实例
19     public GamePlayIG(Object obj) {//我要代理谁
20         this.obj = obj;
21     }
22     //调用被代理的方法
23     public Object invoke(Object proxy, Method method, Object[] args)
24             throws Throwable {
25         Object result = method.invoke(this.obj, args);
26         return result;
27     }
28 }

 

5 AOP实现

加入AOP编程,这里以环绕通知为例,在方法执行的前后加入日志程序。

设定MyMethodInterceptor类:

 1 package com.aop2;
 2 
 3 import org.aopalliance.intercept.MethodInterceptor;
 4 import org.aopalliance.intercept.MethodInvocation;
 5 
 6 public class MyMethodInterceptor implements MethodInterceptor{
 7 
 8     public Object invoke(MethodInvocation arg0) throws Throwable {
 9         System.out.println("写入日志...");
10         Object object = arg0.proceed();
11         System.out.println("日志完成...");
12         return object;
13     }
14 }

修改beans.xml配置:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 4     xmlns:p="http://www.springframework.org/schema/p"
 5     xsi:schemaLocation="http://www.springframework.org/schema/beans 
 6     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
 7 
 8     <!-- 配置被代理对象 -->
 9     <bean id = "message" class = "com.aop2.Message">
10         <property name = "name" value = "alvin"/>
11     </bean>
12     
13     <!-- 配置环绕通知 -->
14     <bean id = "myMethodInterceptor" class = "com.aop2.MyMethodInterceptor"/>
15     
16     <!-- 配置代理对象 -->
17     <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
18         <!-- 代理接口集 -->
19         <property name="proxyInterfaces">
20             <list>
21                 <value>com.aop2.IMessage</value>
22                 <value>com.aop2.IMessage2</value>
23             </list>
24         </property>
25         
26         <!-- 织入通知对象 -->
27         <property name = "interceptorNames">
28             <list>
29                 <value>myMethodInterceptor</value>
30             </list>
31         </property>
32         
33         <!-- 配置被代理对象 -->
34         <property name="target" ref="message" />
35     </bean>
36 
37 </beans>

输出为:

写入日志...
checking alvin
日志完成...
写入日志...
release alvin
日志完成...

可以看到,在执行方法的前后,都有通知织入。

 

 

 

 

posted @ 2014-10-02 23:14  cityflickr  阅读(681)  评论(0编辑  收藏  举报