Spring-构造注入&注解注入&代理模式&AOP

Spring-构造注入&注解注入&代理模式&AOP

一、spring的依赖注入方式

什么叫做注入?
一个类里面依赖于另外一个类,然后spring把类的对象创建出来,然后注入到相应的类里面过程

1.普通的注入

1)普通 set方法注入
​ setName(String name)

<property name="name" value="xxxx">
2.构造参数注入

1.最基本的无引用数据类型构造方法注入

	//java代码构造方法案例
 	public MyBean1(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

方案一:根据构造方法的索引来给属性注入属性值(例)
xml中配置

<!-- 按照索引注入,索引开始为0 -->
<bean id="MyBean" class="cn.itsource._01_.MyBean">
	<constructor-arg index="0" value="666" />
	<constructor-arg index="1" value="张二娃" />
</bean>

方案二:根据构造方法的属性名注入属性值(例)
xml中配置

<!-- 按照名称注入,名称必须一致 -->
<bean id="MyBean" class="cn.itsource._01_.MyBean">
	<constructor-arg name="id" value="1" />
	<constructor-arg name="name" value="张三娃" />
</bean>

方案三:根据构造方法的属性类型注入属性值(不推荐)
xml中配置

<!-- 按照类型注入,必须一一对应,不能有重复的类型-->
<bean id="MyBean" class="cn.itsource._01_.MyBean">
	<constructor-arg type="java.lang.Long" value="1" />
	<constructor-arg type="java.lang.String" value="啦啦啦" />
</bean>

2.1如果有一个参数是我们自己的一个对象,怎么解决?
方法1:直接用ref引用已经定义好的bean

<bean id="otherBean" class="cn.itsource._01_.OtherBean"/>
<bean id="MyBean" class="cn.itsource._01_.MyBean">
	<constructor-arg  value="1" />
	<constructor-arg  value="啦啦啦" />
	<constructor-arg ref="otherBean"/>        <------------看这里
</bean>

方法2:使用一个内部的Bean完成(不需要加id,因为我们无须引用它)

<bean id="MyBean" class="cn.itsource._01_.MyBean">
	<constructor-arg  value="1" />
	<constructor-arg  value="啦啦啦" />
	<constructor-arg>
		<bean class="cn.itsource._01_.OtherBean"/>
	</constructor-arg>
</bean>

2.2.集合(list,set,map …),数组的属性注入(有set,get方法时)

1数组的两种写法:
1.1简写
<property name="arrays" value="A,B,C" />
1.2完整写法
<property name="arrays">
	<array>
		<value>xxx</value>
		<value>yyy</value>
		<value>zzz</value>
	</array>
</property>
2.List<String>
<property name="list">
	<list>
		<value>xxx</value>
		<value>aaa</value>
		<value>bbbb</value>
	</list>
</property>
3.Set<String>
<property name="set">
	<set>
		<value>xxx</value>
		<value>aaa</value>
		<value>bbbb</value>
	</set>
</property>
4.List<OtherBean>
<property name="otherBeanList">
	<list>
		<bean class="cn.itsource._01_.OtherBean" />
		<bean class="cn.itsource._01_.OtherBean" />
		<ref bean="otherBean" />
		<ref bean="otherBean" />
	</list>
</property>
5.Set<OtherBean>
<property name="otherBeanSet">
	<set>
		<bean class="cn.itsource._01_.OtherBean" />
		<bean class="cn.itsource._01_.OtherBean" />
		<ref bean="otherBean" />
		<ref bean="otherBean" />
	</set>
</property>
6.Map
<property name="map">
	<map>
		<entry key="xx" value="value1"></entry>
		<entry key="yy" value="value2"></entry>
	</map>
</property>
3.XML自动注入

3.1byName 按照属性的名称 setXxx方法
配置→

根节点beans   default-autowire="byName" 对当前配置文件的所有bean都生效

3.2 byType按照注入对象的类型
子节点bean autowire="byType"只对当前bean生效

4.全注解配置

第一步:xml约束配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 开启注解扫描,base-package 表示在这个配置下面的所有文件都会被spring扫描 -->
<context:component-scan base-package="cn.itsource" />

第二步:对应的类上面要加上注解
@Component 组件
@Repository 持久层(其实就是dao下面的impl实现层)
@Service service层
@Controller 控制层
第三步:在需要引用其他独享的类中 加上 @Autowired

注意:在spring中引用其他对象时,一般习惯采用引用接口的形式,spring会自己去扫描它的实现类
问题:当假如一个接口有多个实现时,spring就不能知道如何正确的引用,因此需要相应的解决办法

//在实现类上的注解中加上标识
@Repository("userJdbcDao")
public class UserJdbcDaoImpl  implements IUserDao{

方案一:

	@Autowired
	@Qualifier("userJdbcDao")
	private IUserDao userDao;

方案二:

	@Resource(name="userJpaDao")
	private IUserDao userDao;

哪一种更好呢?

首先@Autowired是spring中的注解,他能和Spring进行无缝衔接集成,@Resource是java中自带的注解,虽然他能解决,但是在spring中尽量用spring自己的东西

二、AOP

1.什么是aop?
定义: 面向切面编程(面向方面编程)
2.AOP术语
连接点(Joinpoint):程序执行的某一个特定位置,如类初始前后,方法的运行前后。而Spring只支持方法的连接点。
切点(Pointcut):切点可以定位到相应的连接点,一个切点可以定位多个连接点。
增强(Advice):又被称为通知,完成逻辑的增强。
目标对象(Target):增强逻辑织入的目标类。
引介(Introduction):特殊的增强,为类添加一些属性和方法。
织入(Weaving): 将增强添加到目标类的具体连接点上的过程。Spring使用动态代理织入。
代理(Proxy):一个类(原类)被织入增强(逻辑)后,就产生一个结果类,称为代理类。
切面(Aspect):由切点和增强组成
3.Spring实现AOP的方案
Spring实现Aop有两种方案:JDK代理模式与CGLIB代理模式

Xml版实现AOP

1:xml约束配置

xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd

xml实现aop的四种不同方式
第一种:

<bean id="txManager" class="cn.itsource.controller.TxManager"></bean>
<aop:config>
	<aop:pointcut expression="execution(* cn.itsource.aop.I*Service.*(..))" id="pointcut" />
	<aop:aspect  ref="txManager">
		<!-- 前置通知 -->
		<aop:before method="begin" pointcut-ref="pointcut"/>
		<!-- 后置通知 -->
		<aop:after-returning method="commit" pointcut-ref="pointcut"/>
		<!-- 异常通知 -->
		<aop:after-throwing method="rollback" pointcut-ref="pointcut"/>
		<!-- 最终通知 -->
		<aop:after method="close" pointcut-ref="pointcut" />
	</aop:aspect>
</aop:config>

在这里插入图片描述
TxManager的写法


public class TxManager {
   
    public void begin(){
        System.out.println("开始了");
    }
    
    public void commit(){
        System.out.println("我被提交了");
    }

    public void rollback(Throwable e){
        System.out.println("回滚事务....");
        System.out.println(e.getMessage());
    }

    public void close(){
        System.out.println("关闭了");
    }

第二种方式xml中配置环绕通知

<!--环绕通知:有了环绕,就不需要用另外几个通知(会重复) -->
<aop:around method="around" pointcut-ref="pointcut" />

TxManager的写法

public class TxManager {
   
    public void begin(){
        System.out.println("开始了");
    }
    
    public void commit(){
        System.out.println("我被提交了");
    }

    public void rollback(Throwable e){
        System.out.println("回滚事务....");
        System.out.println(e.getMessage());
    }

    public void close(){
        System.out.println("关闭了");
    }
	public Object around(ProceedingJoinPoint joinPoint){

        Object object = null;
        try {
            begin();
            object = joinPoint.proceed(); //执行相应的代码
            commit();
        } catch (Throwable e) {
            rollback(e);
        }finally{
            close();
        }
        return object;
    }

第三种:.注解版
xml配置

<!-- 组件搜索 -->
<context:component-scan base-package="cn.itsource.aopanno" />
<!-- 支持aop注解 -->
<aop:aspectj-autoproxy />

注解用法

@Component
@Aspect //AOP的类注解
public class TxManager {
	//设置切点
	@Pointcut("execution(* cn.itsource.aopanno.I*Service.*(..))")
	public void pointcut(){}
	//前置通知
	@Before("pointcut()")
	public void begin(){
		System.out.println("开启事务....");
	}
	//后置通知
	@AfterReturning("pointcut()")
	public void commit(){
		System.out.println("提交事务...");
	}
	//异常通知
	@AfterThrowing(pointcut="pointcut()",throwing="e")
	public void rollback(Throwable e){
		System.out.println("回滚事务....");
		System.out.println(e.getMessage());
	}
	//最终通知
	@After("pointcut()")
	public void close(){
		System.out.println("关闭资源....");
	}
}

第四种:注解版的round写法

@Component
@Aspect //AOP的类注解
public class TxManager2 {
    //设置切点
    @Pointcut("execution(* cn.itsource.controller.I*ServiceDao.*(..))")
    public void pointcut() {
    }


    public void begin() {
        System.out.println("开始了");
    }

    public void commit() {
        System.out.println("我被提交了");
    }

    public void rollback(Throwable e) {
        System.out.println("回滚事务....");
        System.out.println(e.getMessage());
    }

    public void close() {
        System.out.println("关闭了");
    }

    @Around("pointcut()")  <--------------------------------------------重点变化
    public Object around(ProceedingJoinPoint joinPoint) {

        Object object = null;
        try {
            begin();
            object = joinPoint.proceed(); //执行相应的代码
            commit();
        } catch (Throwable e) {
            rollback(e);
        } finally {
            close();
        }
        return object;
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值