Spring IOC和aop的原理及实例详解

 更新时间:2019年11月16日 10:19:13   作者:我看见的世界  
这篇文章主要介绍了Spring IOC和aop的原理及实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

这篇文章主要介绍了Spring IOC和aop的原理及实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。特点是面向接口编程,松耦合。

1:IOC(控制反转) 别名(DI:依赖注入)

首先来一段ioc的实现原来代码:

public class ClassPathXmlApplicationContext implements BeanFactory {
 
 private Map<String , Object> beans = new HashMap<String, Object>();
 
 //IOC Inverse of Control DI Dependency Injection
 public ClassPathXmlApplicationContext() throws Exception {
  SAXBuilder sb=new SAXBuilder();
  //解析xml配置文件
  Document doc=sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml"));
  Element root=doc.getRootElement(); //获取根元素
  List list=root.getChildren("bean");//根元素下的子元素
  for(int i=0;i<list.size();i++) {
   Element element=(Element)list.get(i);
   String id=element.getAttributeValue("id");
   String clazz=element.getAttributeValue("class");
   Object o = Class.forName(clazz).newInstance(); //反射获得实例
   System.out.println(id);
   System.out.println(clazz);
   beans.put(id, o);
   //注入bean属性
   for(Element propertyElement : (List<Element>)element.getChildren("property")) {
    String name = propertyElement.getAttributeValue("name"); //userDAO
    String bean = propertyElement.getAttributeValue("bean"); //u
    Object beanObject = beans.get(bean);//UserDAOImpl instance
    
    String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
    System.out.println("method name = " + methodName);
    
    Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
    m.invoke(o, beanObject); 
   }
  } 
 }

 public Object getBean(String id) {
  return beans.get(id);
 }
}
//xml文件
<beans>
 <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" />
 <bean id="userService" class="com.bjsxt.service.UserService" >
  <property name="userDAO" bean="u"/>
 </bean>
 
</beans>

以上代码实现了将UserDAOImpl注入到userService.

值得注意的是:以上操作都是spring帮我们实现的,我们只需要理解如何配置即可。

spring还提供了bean的生存周期和范围属性:

scope:singleton(单例,即每次调用的对象都为同一个)。 prototype(原型,即以bean对象为原型,每次new一个新对象出来)

init-method="init" destroy-method="destroy" lazy-init="true"(延迟初始化bean,即spring启动时,不初始化bean,当需要使用时才实例化,作用:但spring启动缓慢时可使用)

现在基本都是用注解实现,但只要能明白spring是如何实现bean的注入,基本原理都是一样的。spring在中间的作用就是帮我们实现元素之前的注入,谁注入到谁就需要用到不同的注解了。

AOP(切面编程)

首先还是先来一段代码

定义一个InvocationHandler的实现类

public class UserServiceTest {

 @Test
 public void testAdd() throws Exception {
  BeanFactory applicationContext = new ClassPathXmlApplicationContext();

  UserService service = (UserService)applicationContext.getBean("userService");
   
  User u = new User();
  u.setUsername("zhangsan");
  u.setPassword("zhangsan");
  service.add(u);
 }
 
 @Test
 public void testProxy() {
  UserDAO userDAO = new UserDAOImpl();
  LogInterceptor li = new LogInterceptor();
  li.setTarget(userDAO);
  UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);
  
  userDAOProxy.delete();
  userDAOProxy.save(new User());
 }

调用测试类,service和DAO实现类没有贴出来,就是打印一句话出来表现方法执行了。

public class LogInterceptor implements InvocationHandler {
 private Object target;
 public Object getTarget() {
  return target;
 }
 public void setTarget(Object target) {
  this.target = target;
 }

 public void beforeMethod(Method m) {
  System.out.println(m.getName() + " start");
 }

 @Override
 public Object invoke(Object proxy, Method m, Object[] args)
   throws Throwable {
  beforeMethod(m);
  m.invoke(target, args);
  return null;
 }
}

以上代码简单的实现了一个动态代理,并执行了自己的一段逻辑。

那么aop是如何实现切面编程的呢,就是通过动态代理。当然这也是spring来实现的,而我们需要做的就是知道如何编写编织语法。

  • JoinPoint:切入点
  • PointCut: 切入点的集合
  • Aspect:切面
  • Advice: 相当于Aspect的before
  • Around:周围,环绕(需要带参数ProceedingJoinPoint jp)

需要注意的是:被产生代理的对象需要现实接口spring才能产生代理对象,默认使用java se 中的 InvocationHandler 和 proxy 两个类产生代理对象,若没有实现接口,则需要另外引入一个jar包(cglib-nodep-2.1_3.jar);他是通过二进流的方式产生代理对象。

那么spring 帮我们做了什么?

1:充分利用java se 中的反射机制帮助我们对对象的注入,即 IOC,

2: 也是java se 中的动态代理帮助我们实现 切面编程,当然我们也需要熟悉一下asceptj 的切入语法。这就是aop。

所以这里可以总结一下,java se 的特点有反射,动态代理,(这里面必然会用到多态,动态绑定)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java8中List转换String字符串几种方式

    Java8中List转换String字符串几种方式

    这篇文章主要给大家介绍了关于Java8中List转换String字符串的几种方式,在实际开发中经常遇到List转为String字符串的情况,文中给出了几种方法的示例代码,需要的朋友可以参考下
    2023-07-07
  • java 实现web项目启动加载properties属性文件

    java 实现web项目启动加载properties属性文件

    这篇文章主要介绍了java 实现web项目启动加载properties属性文件,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 基于hashmap 的扩容和树形化全面分析

    基于hashmap 的扩容和树形化全面分析

    这篇文章主要介绍了hashmap 的扩容和树形化的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Spring Boot前后端分离开发模式中的跨域问题及解决方法

    Spring Boot前后端分离开发模式中的跨域问题及解决方法

    本文介绍了解决Spring Boot前端Vue跨域问题的实战经验,并提供了后端和前端的配置示例,通过配置后端和前端,我们可以轻松解决跨域问题,实现正常的前后端交互,需要的朋友可以参考下
    2023-09-09
  • Springboot Druid 自定义加密数据库密码的几种方案

    Springboot Druid 自定义加密数据库密码的几种方案

    这篇文章主要介绍了Springboot Druid 自定义加密数据库密码的步骤,帮助大家更好的理解和使用springboot,感兴趣的朋友可以了解下
    2020-12-12
  • 从零开始:快速入门SpringBoot注解的精髓

    从零开始:快速入门SpringBoot注解的精髓

    Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架,它通过使用注解来简化配置和开发过程,使开发人员能够更加专注于业务逻辑的实现,Spring Boot提供了许多注解,用于定义和配置应用程序的各个方面,需要的朋友可以参考下
    2023-10-10
  • Java设计模式笔记之Builder模式

    Java设计模式笔记之Builder模式

    建造者模式是日常开发中比较常见的设计模式,它的主要作用就是将复杂事物创建的过程抽象出来,该抽象的不同实现方式不同,创建出的对象也不同,这篇文章主要给大家介绍了关于Java设计模式笔记之Builder模式的相关资料,需要的朋友可以参考下
    2022-03-03
  • 关于json序列化(javaBean转Json的细节处理)

    关于json序列化(javaBean转Json的细节处理)

    这篇文章主要介绍了关于json序列化(javaBean转Json的细节处理),具有很好的参考价值,希望对大家有所帮助。
    2022-03-03
  • springboot2.0 @Slf4j log 彩色日志配置输出到文件

    springboot2.0 @Slf4j log 彩色日志配置输出到文件

    这篇文章主要介绍了springboot2.0 @Slf4j log日志配置输出到文件(彩色日志),解决方式是使用了springboot原生自带的一个log框架,结合实例代码给大家讲解的非常详细,需要的朋友可以参考下
    2023-08-08
  • Java实现按行分割大文件

    Java实现按行分割大文件

    这篇文章主要为大家详细介绍了Java实现按行分割大文件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05

最新评论