Spring IOC、DI、AOP原理和实现
(1)Spring IOC原理 IOC的意思是控件反转也就是由容器控制程序之间的关系,把控件权交给了外部容器,之前的写法,由程序代码直接操控,而现在控制权由应用代码中转到了外部容器,控制权的转移是所谓反转。网上有一个很形象的比喻:我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法
(1)Spring IOC原理
IOC的意思是控件反转也就是由容器控制程序之间的关系,把控件权交给了外部容器,之前的写法,由程序代码直接操控,而现在控制权由应用代码中转到了外部容器,控制权的转移是所谓反转。网上有一个很形象的比喻:
我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法认识她们, 投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,如果要使用另外的对象, 就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。 那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表, 告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm, 我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的 机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候, 把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象, 而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。 (2)DI(Dependency Injection,依赖注入)IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection, 依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。 在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系 的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。 下面来模拟下IOC和DI的实现原理。 项目的结构图如下: 1、首先定义DAO接口和接口的实现类package com.dao; public interface PersonDAO { public void save(); }
package com.dao.impl; import com.dao.PersonDAO; public class PersonDaoImpl implements PersonDAO { @Override public void save() { System.out.println("保存"); } }
2、创建一个Junit测试类方法instanceSpring1为Spring中的实现用到ClassPathXmlApplicationContext类,要实现IOC的原理要定义自己package com.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.dao.PersonDAO; import com.myUtil.MyClassPathXmlApplicationContext; import com.service.PersonService; public class PersonTest { @Test public void instanceSpring1(){ /** * * spring 的实现 */ //IOC ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml"); PersonDAO pd = (PersonDAO) ac.getBean("personDAO"); pd.save(); //DI PersonService ps = (PersonService) ac.getBean("personService"); ps.save(); } @Test public void instanceSpring2(){ /** * 我的实现 * */ MyClassPathXmlApplicationContext mac = new MyClassPathXmlApplicationContext("beans.xml"); PersonDAO mpd = (PersonDAO) mac.getBean("personDAO"); mpd.save(); //DI PersonService ps = (PersonService) mac.getBean("personService"); ps.save(); } }
的MyClassPathXmlApplicationContext首先读出beans.xml中的配置信息,通过反射机制实现bean,最后注入所需要的
bean。读取所的bean实体package com.myUtil; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class MyClassPathXmlApplicationContext { // xml所有的属性 private ArrayList<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>(); // xml中所有的bean private Map<String, Object> sigletons = new HashMap<String, Object>(); public MyClassPathXmlApplicationContext(String file) { readXml(file); instanceBeans(); instanceObject(); } /** * 注入 */ private void instanceObject() { for (BeanDefinition beanDefinition : beanDefinitions) { //判断有没有注入属性 if (beanDefinition.getProperty() != null) { Object bean = sigletons.get(beanDefinition.getId()); if (bean != null) { try { //得到被注入bean的所有的属性 PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); //得到所有的注入bean属性 for(PropertyDefinition propertyDefinition:beanDefinition.getProperty()){ for(PropertyDescriptor propertyDescriptor:ps){ if(propertyDescriptor.getName().equals(propertyDefinition.getName())){ Method setter = propertyDescriptor.getWriteMethod();//获取set方法 if(setter!=null){ setter.setAccessible(true);//得到private权限 //注入属性 setter.invoke(bean, sigletons.get(propertyDefinition.getRef())); } break; } } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } /** * 实例所有的bean */ private void instanceBeans() { for (int i = 0; i < beanDefinitions.size(); i++) { BeanDefinition bd = beanDefinitions.get(i); try { try { if (bd.getClassName() != null && !bd.getClassName().equals("")) sigletons.put(bd.getId(), Class.forName( bd.getClassName()).newInstance()); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 读xml * * @param file */ private void readXml(String file) { try { SAXReader reader = new SAXReader(); // 使用SAX方式解析XML URL xmlPath = this.getClass().getClassLoader().getResource(file); Document doc = reader.read(xmlPath); Element root = doc.getRootElement(); // 取得根节点 List<Element> beans = root.elements(); for (Element element : beans) { String id = element.attributeValue("id");// id; String clazz = element.attributeValue("class"); BeanDefinition bd = new BeanDefinition(id, clazz); // 读取子元素 if (element.hasContent()) { List<Element> propertys = element.elements(); for (Element property : propertys) { String name = property.attributeValue("name"); String ref = property.attributeValue("ref"); PropertyDefinition pd = new PropertyDefinition(name, ref); bd.getProperty().add(pd); } } beanDefinitions.add(bd); } } catch (Exception e) { // TODO: handle exception } } /** * 通过名字得到bean * * @param str * @return */ public Object getBean(String str) { return sigletons.get(str); } }
package com.myUtil; import java.util.ArrayList; import java.util.List; public class BeanDefinition { private String id; private String className; private List<PropertyDefinition> property = new ArrayList<PropertyDefinition>(); public BeanDefinition(String id, String className) { super(); this.id = id; this.className = className; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public List<PropertyDefinition> getProperty() { return property; } public void setProperty(List<PropertyDefinition> property) { this.property = property; } }
注入属性实体package com.myUtil; public class PropertyDefinition { private String name; private String ref; public PropertyDefinition(String name, String ref) { this.name = name; this.ref = ref; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getRef() { return ref; } public void setRef(String ref) { this.ref = ref; } }
业务接口和实现类package com.service; public interface PersonService { public void save(); }
beans.xml配置package com.service.impl; import com.dao.PersonDAO; import com.service.PersonService; public class PersonServiceImpl implements PersonService{ private PersonDAO pdo; public PersonDAO getPdo() { return pdo; } public void setPdo(PersonDAO pdo) { this.pdo = pdo; } @Override public void save() { pdo.save(); } }
<?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="personDAO" class="com.dao.impl.PersonDaoImpl"></bean> <bean id="personService" class="com.service.impl.PersonServiceImpl"> <property name="pdo" ref="personDAO"></property> </bean> </beans>
(3)AOP面向切面
AOP是OOP的延续,是(Aspect Oriented Programming)的缩写,意思是面向切面编程。要理解AOP首先得弄明白代理的概念。对于代理看下点击打开链接这篇文章。
AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等。 AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理和动态代理两大类,其中静态代理是指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;而动态代理则在运行时借助于 JDK 动态代理、CGLIB 等在内存中"临时"生成 AOP 动态代理类,因此也被称为运行时增强。
知道这些其他的就是些配置了。
简单的实现annotations和xml对AOP的实现。
首先看下目录结构
MyInterceptor、MyInterceptor2分别是以annotations和xml定义的切面类
package com.service;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MyInterceptor {
@Pointcut("execution (* com.serviceImpl.PersonServiceImpl.*(..))")
private void myMethod(){};
@Before("myMethod()")
public void doAccessCheck(){
System.out.println("before");
}
}
package com.service;
public class MyInterceptor2 {
public void doAccessCheck(){
System.out.println("before");
}
}
业务和接口
package com.service;
public interface PersonService {
public void save(String name);
public void update(String name);
}
package com.serviceImpl;
import com.service.PersonService;
public class PersonServiceImpl implements PersonService {
@Override
public void save(String name) {
// TODO Auto-generated method stub
System.out.println("保存");
}
@Override
public void update(String name) {
// TODO Auto-generated method stub
System.out.println("修改");
}
}
简单做个方法前通知 ,其他的都一样。
<?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: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/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:aspectj-autoproxy/>
<bean id="personServiceImpl" class="com.serviceImpl.PersonServiceImpl"></bean>
<bean id="personInterceptor" class="com.service.MyInterceptor2"></bean>
<aop:config>
<aop:aspect id="asp" ref="personInterceptor">
<aop:pointcut id="myCut" expression="execution (* com.serviceImpl.PersonServiceImpl.*(..))"/>
<aop:before pointcut-ref="myCut" method="doAccessCheck"/>
</aop:aspect>
</aop:config>
</beans>
测试类
package com.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.service.PersonService;
public class AopTest {
@Test
public void interceptorTest(){
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
PersonService ps = (PersonService) ac.getBean("personServiceImpl");
ps.save("aa");
}
}
更多推荐
所有评论(0)