Spring学习,依赖注入(DI)、控制反转(IoC)和面向切面(AOP)
2017-02-13 15:16
1016 查看
依赖注入DI和控制反转IoC
Spring容器中的依赖注入DI和控制反转IoC
xml配置
注解配置
面向切面AOP
面向切面的应用动态代理
Spring容器中的面向切面
xml配置
注解配置
Spring整合hibernate和AOP应用之声明式事务
但是这样有个弊端,就是类一开始就定死了,万一业务有变化需要别的实现呢?所以我们要面向接口编程。比如说A类里面需要B类,我们可以将B设计成接口,然后根据业务需求建立不同的B接口实现类B1,B2。。。这样需要什么样的实现就new什么实例。
但是这样还不好,这样设计如果要改实现还要改A类里面的代码替换B接口的实现类,我们可以将实现丢给调用者来实现,在A类里面定义类型B的属性,外部调用者可以通过setter方法和构造方法给该属性赋值一个实现。
这就是注入,将需要的实现通过某些方法给注入进去,依赖注入就是字面上的意思,因为A类的功能依赖B,所以注入B就称作依赖注入,意思就是依赖的东西的注入。而IoC(控制反转)的意思就是依赖的获取被反转了,本来A依赖B,所以A来创建一个实例,但是现在不是由A创建一个实例,而是别人创建好了实例传递给了A。
Spring容器中IoC部分就是做这种事,由Spring创建实例,由Spring进行注入。
注解
一个小区里面的人出小区要经过保安,要进小区也要经过保安,保安可以查看你是不是该小区的人,保安就是切面。
cglib的动态代理(不需要接口的动态代理)
Spring容器中的依赖注入DI和控制反转IoC
xml配置
注解配置
面向切面AOP
面向切面的应用动态代理
Spring容器中的面向切面
xml配置
注解配置
Spring整合hibernate和AOP应用之声明式事务
依赖注入(DI)和控制反转(IoC)
在日常编码中经常遇到在一个类中调用另一个类的多个方法,所以就在一个类中new出需要用到的类,也就是组合模式。比如说A类里面需要用到很多B类里面的方法,所以要在A类里面new一个B。public class A { private B b = new B(); public void aa(){ b.bb(); } }
但是这样有个弊端,就是类一开始就定死了,万一业务有变化需要别的实现呢?所以我们要面向接口编程。比如说A类里面需要B类,我们可以将B设计成接口,然后根据业务需求建立不同的B接口实现类B1,B2。。。这样需要什么样的实现就new什么实例。
package com.jyh.test; public class A { private B b = new B1(); public void aa(){ b.bb(); } public interface B { public void bb(); } public class B1 implements B{ public void bb() { } } public class B2 implements B{ public void bb() { } } }
但是这样还不好,这样设计如果要改实现还要改A类里面的代码替换B接口的实现类,我们可以将实现丢给调用者来实现,在A类里面定义类型B的属性,外部调用者可以通过setter方法和构造方法给该属性赋值一个实现。
package com.jyh.test; public class A { private B b; public A(B b) { super(); this.b = b; } public B getB() { return b; } public void setB(B b) { this.b = b; } public void aa(){ b.bb(); } public static interface B { public void bb(); } public static class B1 implements B{ public void bb() { System.out.println("b1"); } } public static class B2 implements B{ public void bb() { System.out.println("b2"); } } public static void main(String[] args) { A a = new A(new B2()); a.aa(); } }
这就是注入,将需要的实现通过某些方法给注入进去,依赖注入就是字面上的意思,因为A类的功能依赖B,所以注入B就称作依赖注入,意思就是依赖的东西的注入。而IoC(控制反转)的意思就是依赖的获取被反转了,本来A依赖B,所以A来创建一个实例,但是现在不是由A创建一个实例,而是别人创建好了实例传递给了A。
Spring容器中IoC部分就是做这种事,由Spring创建实例,由Spring进行注入。
Spring容器中的依赖注入(DI)和控制反转(IoC)
xml配置
<?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 ht 4000 tp://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- lazy-init,懒加载,在获取bean的时候才创建实例 autowire:自动装配,<property ref/>是指定装配,autowire中byName值就是通过需要注入的属性名字匹配对应id查找bean 比如说本类中有个名为userDao的属性,那么就在这里查找id为userDao的bean来实例化 --> <bean id="userService" class="com.jyh.service.impl.UserServiceImpl" lazy-init="true" autowire="byName"> <!-- property表示注入本类中的某个依赖,name为需要注入的依赖(属性)的名字, ref指向另一个bean的id,也就是说对应属性的类型,如果是基本类型则就用value直接赋值 这个注入是setter方法注入 --> <property name="userDao" ref="userDao" /><!-- bean --> </bean> <!-- dao --> <bean id="userDao" class="com.jyh.dao.impl.UserDaoImpl"></bean> <bean id="user" class="com.jyh.domain.User"> <!-- 基本类型用value直接赋值 --> <property name="name" value="无名"></property> </bean> <!-- 构造方法注入 --> <bean id="userServiceTwo" class="com.jyh.service.impl.UserServiceImpl"> <!-- 指向参数所带表示的实例bean,顺序按照构造方法参数的顺序 --> <constructor-arg ref="userDao"></constructor-arg> <!-- 按照参数类型赋值 <constructor-arg type="java.lang.String" value="构造注入"/> --> <!-- 按照参数名赋值 <constructor-arg name="years" value="7500000"/> <constructor-arg name="ultimateAnswer" value="42"/> --> <!-- 按照参数顺序赋值 <constructor-arg index="0" value="7500000"/> <constructor-arg index="1" value="42"/> --> </bean> </beans>
注解配置
编写注解前需要在xml配置文件中编写如下配置<!-- 将该类下的所有类配置成bean,只需要在该包下的类前面加上@Component(value = beanid)注解就可以不用再配置文件中写bean --> <context:component-scan base-package="com.jyh.annotation"></context:component-scan> <!-- 启动注解 --> <context:annotation-config></context:annotation-config>
注解
package com.jyh.annotation; import javax.annotation.Resource; /** * 注解可以在属性上面也可以在setter方法上面,建议在setter上面 */ import org.springframework.stereotype.Component; @Component(value = "b") //有这个注解就代表着在配置文件中注册了bean(等同于bean标签),value值为bean的id,默认为首字母小写的类名 public class B { private String name; //这两个加一起等同于@Resource(name = "aaa") //@Autowired //默认按照类型匹配 //@Qualifier(value = "aaa") //名称匹配 private A a; public String getName() { return name; } //这个注解代表着这个属性是要通过spring注入来的,等同于bean标签下面的property标签 //name属性代表着该属性在配置文件中bean的id,也就是@Component()标签中的value,没写默认为属性名 @Resource(name = "a") public void setName(String name) { this.name = name; } public A getA() { return a; } public void setA(A a) { this.a = a; } }
面向切面(AOP)
砧板上放了一些面,一刀从中间切下,无论从面的这头到那头还是从那头回到这头都要经过刀面,刀面就是切面。一个小区里面的人出小区要经过保安,要进小区也要经过保安,保安可以查看你是不是该小区的人,保安就是切面。
面向切面的应用:动态代理
JDK自带的动态代理(借助接口实现的动态代理)//JDK自带的动态代理实现,利用接口 @Test public void proxy(){ final UserDao userDao2 = new UserDaoImpl(); UserDao userDao = (UserDao)Proxy.newProxyInstance(UserDaoImpl.class.getClassLoader(), userDao2.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(proxy.getClass().getName()); System.out.println("动态代理"); method.invoke(userDao2,args); return null; } }); userDao.say("nnn"); }
cglib的动态代理(不需要接口的动态代理)
//cglib实现动态代理,不需要接口 @Test public void cglibProxy(){ final UserDao userDao2 = new UserDaoImpl(); Enhancer enhancer = new Enhancer(); //设置拦截器 enhancer.setCallback(new MethodInterceptor() { public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { arg1.invoke(userDao2, arg2); return null; } }); //设置传入被代理的类进去作为父类 enhancer.setSuperclass(userDao2.getClass()); //获取被代理类 UserDao userDao = (UserDao)enhancer.create(); userDao.say("cglib实现动态代理"); }
Spring容器中的面向切面
xml配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:component-scan base-package="com.jyh.annotation"></context:component-scan> <!-- 启动注解 --> <context:annotation-config></context:annotation-config> <!-- 注解aop --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <!-- dao --> <bean id="userDao" class="com.jyh.dao.impl.UserDaoImpl"></bean> <!-- 切面类 --> <bean id="myIntercept" class="com.jyh.aop.MyIntercept"></bean> <!-- aop, proxy-target-class="true"设置用cglib实现代理 --> <aop:config> <!-- 切入点表达式 ,确定目标类,被代理的类,意思就是调用该类中的方法会触发切面 --> <aop:pointcut expression="execution(* com.jyh.dao.impl.UserDaoImpl.*(..))" id="myProxy" /> <!-- ref指向的对象就是切面,也就是公共调用的处理方法所在的类 --> <aop:aspect ref="myIntercept"> <!-- 方法调用前的处理,method指向方法,pointcut-ref指向代理对象,也就是上面pointcut元素的id --> <aop:before method="beforeMethod" pointcut-ref="myProxy" /> <!-- 方法调用后的处理 --> <aop:after-returning method="afterMethod" pointcut-ref="myProxy" returning="val" /> <!-- 无论有没有成功执行,最终都会调用这个方法 --> <aop:after method="finallyMethod" pointcut-ref="myProxy" /> <!-- 异常通知 --> <aop:after-throwing method="exceptionMethod" throwing="ex" pointcut-ref="myProxy" /> <!-- 环绕通知,能控制目标方法执行不执行 --> <aop:around method="aroundMethod" pointcut-ref="myProxy" /> </aop:aspect> </aop:config> </beans>
package com.jyh.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class MyIntercept { public void beforeMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); System.out.println("连接点的名称(方法名称):"+methodName); System.out.println("目标类:"+joinPoint.getTarget().getClass()); System.out.println("方法调用前"); System.out.println("-------------------"); } public void afterMethod(JoinPoint joinPoint,Object val){ System.out.println("目标方法的返回值:" + val); System.out.println("方法调用后"); System.out.println("-------------------"); } public void finallyMethod(){ System.out.println("最后始终会执行的方法"); System.out.println("-------------------"); } public void exceptionMethod(JoinPoint joinPoint,Throwable ex){ System.out.println("异常执行的方法"); System.out.println(ex.getMessage()); System.out.println("-------------------"); } public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("环绕控制前"); joinPoint.proceed();//调用目标方法 System.out.println("环绕控制后"); System.out.println("-------------------"); } }
注解配置
<context:component-scan base-package="com.jyh.annotation"></context:component-scan> <!-- 启动注解 --> <context:annotation-config></context:annotation-config> <!-- 注解aop --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
package com.jyh.annotation; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * @Before方法执行前 @AfterReturning方法执行后 @After最终始终都会执行的方法 * @AfterThrowing异常执行的方法 @Around环绕 * @author OverrideRe * */ @Component("D") @Aspect //表示本类是切面 public class D { //切入点,由于切入点都是方法,所以这里也定义一个方法作为切入点,没有实际意义 @Pointcut("execution(* com.jyh.annotation.C.*(..))") private void cc(){}; @Before("cc()") public void before(){ System.out.println("方法前"); } @AfterReturning("cc()") public void after(){ System.out.println("方法后"); } }
Spring整合hibernate和AOP应用之声明式事务
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 链接数据库的用户名 --> <property name="connection.username">root</property> <!-- 链接数据库的密码 --> <property name="connection.password">ying1995520***</property> <!-- 链接数据库的驱动 --> <property name="connection.driver_class"> com.mysql.jdbc.Driver </property> <!-- 链接数据库的url --> <property name="connection.url"> jdbc:mysql://localhost:3306/db3 </property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hbm2ddl.auto">update</property> <!-- 显示sql语句 --> <property name="show_sql">true</property> <!-- 格式化的显示sql语句 --> <property name="format_sql">true</property> <mapping resource="com/jyh/domain/Account.hbm.xml"/> </session-factory> </hibernate-configuration>
相关文章推荐
- Spring 之 控制反转(IoC), 依赖注入(DI)和面向切面(AOP)
- spring的依赖注入(DI)、控制反转(IOC)和面向切面(AOP)
- Spring学习(三)IOC控制反转与DI依赖注入
- Spring学习之——控制反转(IoC)与依赖注入(DI)
- Spring学习一:IOC(控制反转)和AOP(面向切面)的xml配置和注解方式
- Spring学习(1):控制反转(IoC)和依赖注入(DI)的详解以及注解(annotation)开发入门案例
- Spring 4 学习笔记2:控制反转(IoC)和依赖注入(DI)
- Helloworld之Spring依赖注入/控制反转(DI/IoC)版
- Spring控制反转(IOC)和依赖注入(DI),再记不住就去出家!
- Spring框架运行机制(控制反转,依赖注入,面向切面AOP)
- Spring学习3—控制反转(IOC)基于Annotation(注解)的依赖注入实现
- Spring的依赖注入(DI)和控制反转(IOC)
- Spring入门--控制反转(IOC)与依赖注入(DI)
- 金现代实习,马士兵Spring视频-控制反转(IOC)与依赖注入(DI)
- 如何理解Spring的控制反转IOC和依赖注入DI思想
- Spring反转控制(IOC)和依赖注入(DI)
- Spring 控制反转IOC,依赖注入DI
- Spring环境搭建之:控制反转(IoC Inversion of Control)与依赖注入(DI Depenency Injection)
- java+spring切面编程(aop)spring控制反转(ioc)+hibenrate对象关系映射(ORM) 学习网址
- Spring.Net-DI依赖注入和Ioc控制反转