Spring依赖注入DI & AOP

依赖注入(DI)--手工装配

Spring依赖注入有构造器注入以及setter方法注入两种常用方式,注入依赖对象可以采用手工装配和自动装配两种手段,但是推荐使用的是手动装配,自动装配无法掌握注入的结果。

既然说是手工装配,这里先得创建一个对象类,声明几个不同类型的成员,来看看如何手动装配的

public class User {
	private long id;
	private String name;
	private int age;
	public User() {
		
	}
	public User(long id, String name, int age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}
}

使用Xml配置注入依赖对象,在xml配置文件中,创建bean节点,在其中配置若使用的是带参构造器配置,需要在<constructor-arg>标签配置,需要注意的就是数据类型,基本数据类型则直接写类型和参数即可,如果是引用类型则需要加上包的路径如:java.lang.Long;而若是使用setter方法配置则在<property>标签中配置属性的名称以及属性值。

<bean id="orderService" class="cn.com.chongking.People">
   <constructor-arg index=“0” type=“long” value=“1”/>//构造器注入(带参构造函数第1个值)
   <constructor-arg index=“1” type=“java.lang.String” value=“李四”/>//构造器注入(带参构造函数第2个值)
   <constructor-arg index=“2” type=“int” value=“22”/>//构造器注入(带参构造函数第3个值)  
    <property name=“name” value=“李四”/>//属性setter方法注入
</bean>

除了可以在xml文件中配置,还可以通过注解配置,虽然是通过注解配置,但是在xml文件中的一些配置也是不可缺少的,约束文件的请求头以及使用注解配置的声明。

<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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.1.xsd">
          <context:annotation-config/>
</beans>
<!-- 命名空间 -->
xmlns:context="http://www.springframework.org/schema/context"
<!-- 约束文件的引入 -->
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
<!-- 使用注解的声明 -->
<context:annotation-config/>

java代码中使用@Autowired@Resource注解方式进行装配,@Autowired注解是名称装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false @Autowired (required=false)。如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下:

@Autowired 

@Qualifier("personDaoBean")

private PersonDao  personDao;

@Resource注解和@Autowired一样,也可以标注在字段或属性的setter方法上,但它默认按名称装配。名称可以通过@Resourcename属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。

@Resource(name=“personDao”)

private PersonDao  personDao;//用于字段上

   如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, @Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了

    @Autowired 
    private PersonDao  personDao;//用于字段上(属性可不用Setter方法)

    @Autowired
    public void setOrderDao(OrderDao orderDao) {//用于属性的setter方法上
        this.orderDao = orderDao;//可省略
    }

自动扫描

前面的例子我们都是使用XMLbean定义来配置组件。在一个稍大的项目中,通常会有上百个组件,如果这些这组件采用xmlbean定义来配置显然会增加配置文件的体积查找及维护起来也不太方便。spring2.5为我们引入了组件自动扫描机制,他可以在类路径底下寻找标注了@Component@Service@Controller@Repository注解的类,并把这些类纳入进spring容器中管理它的作用和在xml文件中使用bean节点配置组件是一样的要使用自动扫描机制,我们需要打开以下配置信息:

<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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.1.xsd">
       <!-- 配置自动扫描的包 -->
       <context:component-scan base-package="com.ozc"/>
</beans>

其中base-package为需要扫描的包(含子包)。

@Service用于标注业务层组件、 @Controller用于标注控制层组件(如struts中的action)、@Repository用于标注数据访问组件,即DAO组件。而@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

AOP概述

AOPAspect Oriented Programming),即面向切面编程,可以说是OOPObject Oriented Programming,面向对象编程)的补充和完善。它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性

Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象(切面就是一个关注点的模块化,譬如:事务管理、日志记录、权限管理都是所谓的切面).

joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)

Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义.

Advice(通知):所谓通知是指拦截到joinpoint(方法)之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知

Target(目标对象):代理的目标对象

Weave(织入):指将aspects (切面)应用到target对象并导致proxy对象创建的过程称为织入.

AOP图解

Spring--AOP编程

要进行AOP编程,首先我们要在spring的配置文件中引入aop命名空间:

<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-3.1.xsd
       <!-- xsd约束文件 -->
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">

</beans>

同样的AOP的配置方式一样有xml和注解两种配置方式,相似的是都需要一个切面工具类。

注解配置,需要引入AOP的命名空间在配置以下配置

<!--  配置AOP注解配置-->
<aop:aspectj-autoproxy/>
<bean id="userInterceptor“ class="com.ozc.common.UserInterceptor"/>
<bean id="userService" class="com.ozc.service.UserService"/>
@Aspect
@Component
public class UserInterceptor {
	@Pointcut("execution (* cn.com.chongking.aop.annotation.UserServiceBean.*(..))")
	private void anyMethod() {
	}// 声明一个切入点(定义要拦截的方法)
	// && args(name)意思是:除了要满足上面的execution (*
	// cn.com.chongking.aop.annotation.UserServiceBean.*(..))之外还要满足这个方法中的
	// 参数个数是一个;参数类型是String

	@Before("anyMethod() && args(name)")
	// anyMethod是切入点的名称(就是上面的切入点方法名);args(name)和下面方法中的name一致
	public void doAccessCheck(String name) {
		System.out.println("前置通知:" + name);
	}

	@AfterReturning(pointcut = "anyMethod()", returning = "user")
	public void doAfterReturning(UserInfo user) {// 定义后置通知
		System.out.println("后置通知:" + user);
	}

	@After("anyMethod()")
	public void doAfter() {
		System.out.println("最终通知");
	}

	@AfterThrowing(pointcut = "anyMethod()", throwing = "e")
	public void doAfterThrowing(Exception e) {// 例外通知
		System.out.println("例外通知:" + e);
	}

	@Around("anyMethod()")
	// 环绕通知(格式基本上是固定的)
	public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
		// if(){//判断用户是否在权限
		System.out.println("进入环绕通知方法");
		Object result = pjp.proceed();
		System.out.println("退出环绕通知方法");
		// }
		return result;
	}
}

使用xml配置声明切面

<bean id="departInterceptorBean" class="cn.com.chongking.aop.xml.DepartInterceptor"/>
    <bean id="departServiceBean" class="cn.com.chongking.aop.xml.DepartService"/>
    <!-- AOP配置 -->
<aop:config>
    <!-- 定义一个切面 -->
    <aop:aspect id="asp" ref="departInterceptorBean">
         <aop:pointcut id=“pc1” 
         expression=“execution (*  com.zrcx.service.DepartService.*(..))"/>
         <!-- 定义前置通知;通知方法名:doAfter;引用的切入点:pc1-->
         <aop:before pointcut-ref=“pc1" method="doBefore"/>
         <!-- 定义后置通知 -->
         <aop:after-returning pointcut-ref=“pc1" method="doAfterReturning"/>
         <!-- 定义例外通知 -->
         <aop:after-throwing pointcut-ref=“pc1” method="doAfterThrowing"/>
         <!-- 定义最终通知 -->
         <aop:after pointcut-ref=“pc1” method="doAfter"/>
         <!-- 定义环绕通知 -->
         <aop:around pointcut-ref=“pc1” method="doAround"/>
    </aop:aspect>
</aop:config>

DepartInterceptor.java

public class DepartInterceptor {
	// 切面(注意下面这些方法没有参数)
	public void doAccessCheck() {// 前置通知
		System.out.println("前置通知:");
	}

	public void doAfterReturning() {// 定义后置通知
		System.out.println("后置通知:");
	}

	public void doAfter() {
		System.out.println("最终通知");
	}

	public void doAfterThrowing() {// 例外通知
		System.out.println("例外通知:");
	}

	// 环绕通知(格式基本上是固定的)
	public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
		// if(){//判断用户是否在权限
		System.out.println("进入环绕通知方法");
		Object result = pjp.proceed();
		System.out.println("退出环绕通知方法");
		// }
		return result;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值