一、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,实现起来更复杂。这里只是浅析,有助于理解吧。