首页 > 代码库 > 关于Spring的一些笔记

关于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 = "http://www.mamicode.com/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 = "http://www.mamicode.com/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 = "http://www.mamicode.com/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
日志完成...

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

 

 

 

 

关于Spring的一些笔记