首页 / 更多教程 / Spring IOC 和 AOP
Spring IOC 和 AOP
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Spring IOC 和 AOP,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含12281字,纯文字阅读大概需要18分钟。
内容图文
![Spring IOC 和 AOP](/upload/InfoBanner/zyjiaocheng/1017/31d79cfc19424c529ce51cd202003769.jpg)
Spring框架中的 IOC 和 AOP
参考博客:https://www.cnblogs.com/xiaoxing/p/5836835.html
一.什么是Spring?
Spring是一个轻量级开源框架,开发目的是为了解决企业应用开发的复杂性,Spring通过bean来管理java类,将java类封装进容器里,需要时便可以为你提供
对应类的对象。可以说,Spring是一个轻量级的控制反转IOC和面向切面AOP的容器框架。Spring框架简单、易于测试,最重要的是它可以做到松耦合,这不仅仅
对服务端应用受益,对所有java应用都有好处。
二.如何简单搭建一个Spring框架?
1.首先在maven中导入spring的整合包
<!--spring相关--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.17.RELEASE</version> </dependency>
2.在maven中可以看到以下jar包
3.创建一个spring.xml文件,用作spring的配置
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean></bean> </beans>
4.创建一个类,将其注入到Spring容器里
User类
public class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } public User(){ } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
spring.xml
<bean id="entity" class="test.entity.User"> <property name="name" value="测试"/> <property name="age" value="11"/> </bean>
5创建一个Test类,测试是否能拿到Spring中返回的对象
public static void main(String[] args) { ApplicationContext ac = new FileSystemXmlApplicationContext("classpath:spring.xml"); User user = (User) ac.getBean("entity"); System.out.println(user.getName()); System.out.println(user.getAge()); }
测试结果,成功拿到返回对象的成员变量的值
三.Spring框架中的主要模块
Spring框架中主要包含六大模块:Core、Dao、Orm、Jee、Web、Aop
Spring DAO:Spring提供了对JDBC的操作支持:JdbcTemplate模板工具类 。
Spring ORM:Spring可以与ORM框架整合。例如Spring整合Hibernate框架,其中Spring还提供HibernateDaoSupport工具类,简化了Hibernate的操作 。
Spring WEB:Spring提供了对Struts、Springmvc的支持,支持WEB开发。与此同时Spring自身也提供了基于MVC的解决方案 。
Spring AOP:Spring提供面向切面的编程,可以给某一层提供事务管理,例如在Service层添加事物控制 。
Spring JEE:J2EE开发规范的支持,例如EJB 。
Spring Core:提供IOC容器对象的创建和处理依赖对象关系 。
四.什么是IOC?Spring中如何实现IOC?
IOC容器概念:IOC容器指具有依赖注入功能的容器,具有创建对象功能的容器。IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。在Java中
我们平时创建一个对象的做法就是去new它,但是IOC(控制反转)的思想就是不由程序员手动去做这个事,而是让程序自己去做这个事,在spring中实现IOC思想的就是Spring容器,
将创建对象的工作都交由Spring容器来做。
DI(依赖注入Dependency injection) :在容器创建对象后,处理对象的依赖关系。自动将配置好的内容填充到对象里。
依赖注入有以下几种方式:
1.set注入
创建一个Friend类
public class Friend { private String name; private int age; private String address; /* get和set方法 */ }
修改之前的User类
public class User { private String name; private int age; private Friend friend; /* set和get方法 */ /* 重写toString()方法 */ }
在Spring.xml文件中配置
<bean id="friend" class="test.entity.Friend"> <property name="name" value="张三"/> <property name="age" value="13"/> <property name="address" value="X街道X楼"/> </bean> <bean id="entity" class="test.entity.User"> <property name="name" value="测试"/> <property name="age" value="11"/> <property name="friend" ref="friend"/> </bean>
测试Spring是否能够成功创建User对象
ApplicationContext ac = new FileSystemXmlApplicationContext("classpath:spring.xml"); User user = (User) ac.getBean("entity"); System.out.println(user.toString());
输出结果:
2.构造器注入
分别给User类和Friend类设置有参构造方法
public User(String name, int age, Friend friend) { this.name = name; this.age = age; this.friend = friend; }
public Friend(String name, int age, String address) { this.name = name; this.age = age; this.address = address; }
Spring.xml配置
<!--构造器注入--> <bean id="friend" class="test.entity.Friend"> <constructor-arg name="age" value="11"/> <constructor-arg name="name" value="李四"/> <constructor-arg name="address" value="XX街道XX号楼"/> </bean> <bean id="entity" class="test.entity.User"> <constructor-arg name="name" value="person"/> <constructor-arg name="age" value="12"/> <constructor-arg name="friend" ref="friend"/> </bean>
构造器注入和类的构造方法相互对应,如果在xml文件中配置的参数个数和构造方法里的对应不上就会报错,实现原理就是通过参数来找到对应类
的构造方法并且创建出对象
测试输出结果:
3.基于注解
在User类和Friend类上加上@Component注解,表示把这两个类注入Spring容器,作为Spring的组件,去掉get和set方法
@Component public class User { private String name; private int age; @Autowired//自动注入 private Friend friend; public User(String name, int age, Friend friend) { this.name = name; this.age = age; this.friend = friend; } public User(){ } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", friend=" + friend + '}'; } }
@Component public class Friend { private String name; private int age; private String address; public Friend() { } public Friend(String name, int age, String address) { this.name = name; this.age = age; this.address = address; } @Override public String toString() { return "Friend{" + "name='" + name + '\'' + ", age=" + age + ", address='" + address + '\'' + '}'; } }
spring.xml配置
<bean id="user" class="test.entity.User"/> <bean id="friend" class="test.entity.Friend"/>
在User类中使用@Autowired自动注入friend对象
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring.xml"); User user = (User) ac.getBean("user"); System.out.println(user.toString());
测试结果
成功获取user对象,friend对象也成功注入
4.在@configuration注解的配置类中注入
创建一个@configuration注解的类
@Configuration public class Beans { @Bean public Friend friend(){ return new Friend("张三", 12, "中央大街"); } @Bean public User user(Friend friend){ return new User(); } }
获取User类对象
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring.xml"); User user = (User) ac.getBean(User.class); System.out.println(user.toString());
运行结果
成功获取user对象 ,并且Friend类成功注入到User类中
Spring注入相关的注解
@Component 把对象加入ioc容器,对象引用名称是类名,第一个字母小写 @Component(“name”) 把指定名称的对象,加入ioc容器 @Repository 主要用于标识加入容器的对象是一个持久层的组件(类) @Service 主要用于标识加入容器的对象是一个业务逻辑层的组件 @Controller 主要用于标识加入容器的对象是一个控制层的组件 @Resource 注入属性(DI), 会从容器中找对象注入到@Resource修饰的对象上 @Autowired 注入属性(DI), 会从容器中找对象注入到@Autowired修饰的对象上
@Autowired和@resource的区别
一.
@Autowired是根据类型注入的
@Resource是先根据名字,再根据类型注入,@Resource后面可以指定bean的name注入,这样就只会通过名字来注入,如@Resource("test")只会查找id为test的bean注入
二.
@Autowired是Spring中的注解,而@Resource是jdk自带的,是属于j2ee的注解
五.什么是AOP?Spring中如何实现AOP?
AOP是面向切面编程,通俗来讲就是把每个业务中都需要写的同样的代码提取出来,写好后放入每个类的相应的切点,Spring容器会动态地在这些切点位置织入我们写好的代码。
这样做能够大大减少代码的冗余。
AOP涉及名称:
切面(Aspect):其实就是共有功能的实现。如日志切面、权限切面、事务切面等。在实际应用中通常是一个存放共有功能实现的普通Java类,之所以能被AOP容器识别成切面,是在配置中指定的。
通知(Advice):是切面的具体实现。以目标方法为参照点,根据放置的地方不同,可分为前置通知(Before)、后置通知(AfterReturning)、异常通知(AfterThrowing)、最终通知(After)与环绕通知(Around)5种。在实际应用中通常是切面类中的一个方法,具体属于哪类通知,同样是在配置中指定的。
连接点(Joinpoint):就是程序在运行过程中能够插入切面的地点。例如,方法调用、异常抛出或字段修改等,但Spring只支持方法级的连接点。
切入点(Pointcut):用于定义通知应该切入到哪些连接点上。不同的通知通常需要切入到不同的连接点上,这种精准的匹配是由切入点的正则表达式来定义的。
目标对象(Target):就是那些即将切入切面的对象,也就是那些被通知的对象。这些对象中已经只剩下干干净净的核心业务逻辑代码了,所有的共有功能代码等待AOP容器的切入。
代理对象(Proxy):将通知应用到目标对象之后被动态创建的对象。可以简单地理解为,代理对象的功能等于目标对象的核心业务逻辑功能加上共有功能。代理对象对于使用者而言是透明的,是程序运行过程中的产物。
织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程。这个过程可以发生在编译期、类装载期及运行期,当然不同的发生点有着不同的前提条件。譬如发生在编译期的话,就要求有一个支持这种AOP实现的特殊编译器;发生在类装载期,就要求有一个支持AOP实现的特殊类装载器;只有发生在运行期,则可直接通过Java语言的反射机制与动态代理机制来动态实现。
在Spring中实现AOP
首先创建一个切面类
@Aspect //设置为切面类 @Component //注入spring public class LogAspect { //以字符串形式表示执行目标条件,得使用final来修饰 //切点表达式 private final String Exec = "execution(* aop.test.service..*.*(..))"; @Pointcut(Exec) public void pointMethode(){}//设置切入点 //执行顺序:环绕通知(前),前置通知,环绕通知(后),后置通知,返回后通知 @Before("pointMethode()")// 方法执行前执行 public void before(){ System.out.println("method before"); } @After("pointMethode()")// 方法执行后执行 public void after(){ System.out.println("method after"); } @AfterReturning("pointMethode()")// 方法返回后执行 public void afterReturning(){ System.out.println("method afterReturning"); } @AfterThrowing("pointMethode()")// 方法抛异常后执行 public void afterThrowing(){ System.out.println("method afterThrowing"); } @Around("
pointMethode()
")// 环绕通知 public void around(ProceedingJoinPoint pr){ System.out.println("method around bg"); try { pr.proceed();// 执行目标方法 MethodSignature signature = (MethodSignature) pr.getSignature();//获取切点对象 Method method = signature.getMethod();//获取方法 } catch (Throwable e) { e.printStackTrace(); } System.out.println("method around ed"); } }
execution(* aop.test.service..*.*(..)) ,pointMethode中的三个"*"中,第一个*代表返回值,第二*代表service下子包,第三个*代表方法名,“(..)”代表方法参数。
现在的切入点为service类中的所有方法
创建一个service类,并且注入Spring容器
@Service(value = "aopService") public class AopTestService { @LogAspect("show") public void method1(){ System.out.println("执行method1"); } public void method2(){ System.out.println("执行method2"); } }
创建测试方法,执行service类中的切点方法
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:spring.xml") public class Test { @Resource(name = "aopService") private AopTestService aopTestService; @org.junit.Test public void fun(){ aopTestService.method1(); aopTestService.method2(); } }
运行结果
通过自定义注解实现AOP
自定义注解类
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface LogAspect { String value() default ""; }
在service类的切点方法上添加注解
@LogAspect("show") public void method1(){ System.out.println("执行method1"); }
修改切面类
@Before("@annotation(aop.test.annoation.LogAspect)")// 方法执行前执行 public void before(){ System.out.println("method before"); } @After("@annotation(aop.test.annoation.LogAspect)")// 方法执行后执行 public void after(){ System.out.println("method after"); } @AfterReturning("@annotation(aop.test.annoation.LogAspect)")// 方法返回后执行 public void afterReturning(){ System.out.println("method afterReturning"); } @AfterThrowing("@annotation(aop.test.annoation.LogAspect)")// 方法抛异常后执行 public void afterThrowing(){ System.out.println("method afterThrowing"); } @Around("@annotation(aop.test.annoation.LogAspect)")// 环绕通知 public void around(ProceedingJoinPoint pr){ System.out.println("method around bg"); try { pr.proceed();// 执行目标方法 MethodSignature signature = (MethodSignature) pr.getSignature();//获取切点对象 Method method = signature.getMethod();//获取方法 } catch (Throwable e) { e.printStackTrace(); } System.out.println("method around ed"); }
在测试方法中执行method1
内容总结
以上是互联网集市为您收集整理的Spring IOC 和 AOP全部内容,希望文章能够帮你解决Spring IOC 和 AOP所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。