一、Spring IOC
為使用Spring IoC容器,應用代碼可以通過下面兩個接口完成:

1.BeanFactory。當應用創建BeanFactory實例時,實際上是完成了JavaBean的實例化、配置以及管理。

 Resource resource = new ClassPathResource("appcontext.xml");
 BeanFactory factory = new XmlBeanFactory(resource);
 HelloWord hw = (HelloWorld)factory.getBean("fileHelloWorld");
 
 appcontext.xml的部分內容如下示例:

 1  <beans>
 2   <bean name="hello" class="com.taiji.HelloWorld">
 3   <property name='hello'>
 4     <value>I love you!</value>
 5   </property>
 6   <property name='person'>
 7     <ref bean="person" />
 8   </property
 9   </bean>
10   <bean name="person">
11 <property name='name'>
12     <value>Liu</value>
13   </property>
14   <property name='age'>
15     <value>25</value>
16   </property
17 </bean>
18  </beans>

 
2.ApplicationContext。繼承于BeanFactory,主要用于J2EE開發,也是Spring推薦使用的接口。對于Web應用而 言,當J2EE Web應用部署并啟動時,Spring ApplicationContext將會自動被實例化。通過ContextLoaderServlet和ContextLoaderListener能 夠自動創建ApplicationContext實例,開發者也可以手動創建。對于struts,采用PlugIn的方式加載是一個非常好的方式。見前面 的struts和spring的整合方案。

那么Spring是怎么做到IOC的呢?Java的反射即可實現IOC機制,通過反射可以生成對象實例,并且通過調用其set方法設置對象的屬性:

public static Object newInstance(String className) {
  Class
<?> cls = null;
  Object obj 
= null;
  
try {
   cls 
= Class.forName(className);
   obj 
= cls.newInstance();
  } 
catch (ClassNotFoundException e) {
   
throw new RuntimeException(e);
  } 
catch (InstantiationException e) {
   
throw new RuntimeException(e);
  } 
catch (IllegalAccessException e) {
   
throw new RuntimeException(e);
  }
  
return obj;
 }

public static void setProperty(Object obj, String name, String value) {   
            Class
<? extends Object> clazz = obj.getClass();   
            
try {   
                String methodName 
= returnSetMthodName(name);   
                Method[] ms 
= clazz.getMethods();   
                
for (Method m : ms) {   
                    
if (m.getName().equals(methodName)) {   
                        
if (m.getParameterTypes().length == 1) {   
                            Class
<?> clazzParameterType = m.getParameterTypes()[0];   
                            setFieldValue(clazzParameterType.getName(), value, m,   
                                    obj);   
                            
break;   
                        }   
                    }   
                }   
            } 
catch (SecurityException e) {   
                
throw new RuntimeException(e);   
            } 
catch (IllegalArgumentException e) {   
                
throw new RuntimeException(e);   
            } 
catch (IllegalAccessException e) {   
                
throw new RuntimeException(e);   
            } 
catch (InvocationTargetException e) {   
                
throw new RuntimeException(e);   
            }   
    } 

 

IOC不難吧,你也可以做一個IOC框架哦?

二、Spring AOP

Spring的AOP要復雜一些,不是僅僅搞個反射就能解決的。AOP最簡單的實現機制就是JAVA的動態代理。

動態代理在調用真正的業務類方法之前或之后都插入了代碼,這就是JDK的動態代理做的事情,如下是一個動態代理的例子:

public interface Action {

void method();

}

public class ActionImpl  implements Action
{
   public void mothod() {

   System.out.println(
"Action!");

 }
}
public class MyInvocationHandler implements InvocationHandler {

private Object obj;

public MyInvocationHandler(Object obj) {

this.obj = obj;

}

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

System.out.println(
"Before Action");

Object returnObject 
= method.invoke(obj, args);

System.out.println(
"After Action.");

return returnObject;


public static void main(String[] args) throws InterruptedException,

IllegalArgumentException, SecurityException,

InstantiationException, IllegalAccessException,

InvocationTargetException, NoSuchMethodException {

//實現業務邏輯的類

ActionImpl a
= new ActionImpl();

//JDK創建的動態邏輯類,調用上面的構造函數注入

MyInvocationHandler myInvocation 
= new MyInvocationHandler(a);


//建業務邏輯類的動態代理類

Object proxy 
= Proxy.newProxyInstance(ActionImpl.class.getClassLoader(),
       ActionImpl.
class.getInterfaces(), myInvocation);

//業務類自己調用運行代理對象

Action action
= (Action) proxy;

    action.
method();

}

}

運行后會打印出:

Before Action.

Action!

After Action.

Java的動態代理有一個缺陷,它代理的類必須有一個接口類,否則就不能實現動態代理。在面向接口的編程里面,也許不會有問題,但是事情總是有特殊,那如何實現呢?在Spring中是通過CGLIB來實現的。CGLIB可以直接對類進行增強。如下代碼對一個類進行增強:

public class MyClass {
 
    
public void method() {
        System.out.println(
"MyClass.method()");
    }
}

import java.lang.reflect.Method;
 
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.MethodInterceptor;
 
public class Main {
 
    
public static void main(String[] args) {
 
        Enhancer enhancer 
= new Enhancer();
 
        enhancer.setSuperclass(MyClass.
class);
        enhancer.setCallback( 
new MethodInterceptorImpl() );
 
 
        MyClass my 
= (MyClass)enhancer.create();
 
        my.method();
    }

}

class MethodInterceptorImpl implements MethodInterceptor {
        
        
public Object intercept(Object obj, 
                                Method method, 
                                Object[] args, 
                                MethodProxy proxy) 
throws Throwable {
 
            System.out.println(method);
 
            proxy.invokeSuper(obj, args);
 
            
return null;
        }
}



執行結果:
public void MyClass.method()
MyClass.method()

可以看到通過CGLIB實現類方法的增加并不比動態代理復雜。當然Spring中需要考慮的東西更多,具體可以研究org.springframework.aop.framework.Cglib2AopProxy.java,實現起來更復雜。這里只是淺析,有助于理解吧。