欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring依赖注入和springAOP

程序员文章站 2022-04-25 21:26:28
...

1.依赖注入

依赖注入,是IOC的一个方面,是个通常的概念,它有多种解释。这概念是说你不用创建对象,而只需要描述它如何被创建。你不用在代码里直接new对象,统一交给spring容器管理,spring容器(IOC容器)负责把他们组装起来。

导包:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.itsource</groupId>
    <artifactId>spring-day2</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.8</version>
        </dependency>


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
           <resource>
               <directory>src/test/java</directory>
               <includes>
                   <include>**/*.xml</include>
               </includes>
           </resource>
        </resources>
    </build>
</project>

实体类

2依赖注入方式

1.构造器方式,需要有参构造,一个参数对应一个值,不需要提供get/set

2.1.方案一:根据构造器参数的顺序(索引)

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

2.2.方案二:根据构造器参数的名称

<!-- 按照名称注入,名称必须一致 -->
<bean id="MyBean" class="cn.itsource._01_.MyBean">
	<constructor-arg name="id" value="12222" />
	<constructor-arg name="name" value="你是谁" />
</bean>

2.3.方案三:根据构造器的类型注入

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

1 类里面有对象怎么注入
1,现在外面定义好,然后ref引用

<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="MyBean" class="cn.itsource._01_.MyBean">
	<constructor-arg  value="122" />
	<constructor-arg  value="撒打算" />
	<constructor-arg>
		<bean class="cn.itsource._01_.OtherBean"/>
	</constructor-arg>
</bean>

2 set/get 方式注入和 集合注入
定义个类 set get省略

 private Long id;
    private String name;
    private Boolean sex;
    private BigDecimal salary;
    //数组注入
    private String[] arrays;

    private List<String> list;
    private List<OtherBean> otherBeanList;
    private Set<String> set;
    private Set<OtherBean> otherBeanSet;
    
	//Map注入
    private Map<String,String> mp;
    //Properties掌握
    private Properties prop1;
    private Properties prop2;

set/get注入

        <property name="id" value="1"></property>
        <property name="name" value="啊大大"></property>
        <property name="sex" value="true"></property>
        <property name="salary" value="22222.2222"></property>
</bean>
 <!-- 注入数组-->
        <!--简写-->
        <!--<property name="arrays" value="1,2,4"></property>-->
        <!--完整写法-->
        <property name="arrays">
            <array>
                <value>111</value>
                <value>2222</value>
                <value>333</value>
            </array>
        </property>

下面是剩余注入

 <!-- list注入-->
        <property name="list">
            <array>
                <value>哈哈哈</value>
                <value>呵呵呵</value>
                <value>333</value>
            </array>
        </property>

        <property name="otherBeanList">
            <list>
                <!--这三个是不同的对象 因为每次都是新创建的-->
                <bean class="cn.itsource._01di.OtherBean"></bean>
                <bean class="cn.itsource._01di.OtherBean"></bean>
                <bean class="cn.itsource._01di.OtherBean"></bean>
                <!--这个是先创建好了  直接引用 所以地址是一样的-->
                <ref bean="otherBean"></ref>
                <ref bean="otherBean"></ref>
            </list>
        </property>
        <!--set注入  跟list 是一样的-->
        <property name="set">
            <array>
                <value>哈哈哈</value>
                <value>呵呵呵</value>
                <value>333</value>
            </array>
        </property>

        <property name="otherBeanSet">
            <set>
                <!--这三个是不同的对象 因为每次都是新创建的-->
                <bean class="cn.itsource._01di.OtherBean"></bean>
                <bean class="cn.itsource._01di.OtherBean"></bean>
                <bean class="cn.itsource._01di.OtherBean"></bean>
                <!--这个是先创建好了  直接引用 所以地址是一样的-->
                <ref bean="otherBean"></ref>
                <ref bean="otherBean"></ref>
            </set>
        </property>
        <!--map 方式注入-->
        <property name="mp">
            <map>
                <entry key="111" value="呜呜呜呜"></entry>
                <entry key="2222" value="哇哇哇"></entry>
            </map>
        </property>

这里重点说一下 配置properties 对象

<!-- prop配置 properties key value-->
<!-- 支持中文-->
<property name="prop1">
    <props>
        <prop key="key1">dadad</prop>
        <prop key="key2">ghahhah擦打打敖德萨多阿达</prop>
    </props>
</property>
<!--不支持中文-->
<property name="prop2">
    <value>
        key1=222
        key2=祝您哈比啊
    </value>
</property>

3 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 http://www.springframework.org/schema/beans/spring-beans.xsd"
       default-autowire="byName">
    <!--default-autowire="byType"
       如果这里用类型注入,可能会出现找不到
       然后需要在注入层 加上autowire="byName"
		根节点beans   default-autowire="byName" 对当前配置文件的所有bean都生效
		子节点bean autowire="byType"只对当前bean生效
       或者可以改成 default-autowire="byName"
       根据名字
    -->
   <!-- <bean id="userDao" class="cn.itsource._02_xmlauto.UserDao"></bean>
    <bean id="userService" class="cn.itsource._02_xmlauto.UserService"></bean>
    <bean id="userServicex" class="cn.itsource._02_xmlauto.UserService"></bean>
    <bean id="userController" class="cn.itsource._02_xmlauto.UserController"></bean>-->
</beans>

4 全注解配置

1 配置context命名空间

<?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">

2 .:配置让Spring扫描类与支持注解

<!-- 
	@Component  普通仓库
	@Repository  仓库(其实就是dao层)
	@Service	service层
	@Controller  控制层(servlet、action)
 -->
<!-- 进行包的扫描,去看类上面是否有相应的标签配置 -->
<context:component-scan base-package="cn.itsource._03_anno" />

然后在类上面加注解

@Repository
public class UserDao {
	public void save(){
		System.out.println("保存数据xxxx....");
	}
}

@Service
public class UserService {
	@Autowired
	private UserDao userDao;
	public void save(){
		userDao.save();
	}
}


@Controller
@Scope(“prototype”)
public class UserAction {
	@Autowired
	private UserService userService;
	public String save(){
		userService.save();
		return "success";
	}
}

2 springAOP

定义: 面向切面编程(面向方面编程)
使用场景:事务管理 日志管理 性能监控 拦截器

2.1AOP的 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:aop="http://www.springframework.org/schema/aop"
       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
                http://www.springframework.org/schema/aop
                http://www.springframework.org/schema/aop/spring-aop.xsd"
    >
    <!-- 开启扫描 controller service repository component-->
    <context:component-scan base-package="cn.itsource._04_xmlaop"/>
    <!-- aop的配置-->
    <aop:config>
        <aop:pointcut expression="execution(* cn.itsource._04_xmlaop.I*Service.*(..))" id="pointcut" />
        <!-- aspect方面或者切面-->
        <aop:aspect ref="txmanager">
            <!--前置通知-->
            <aop:before method="begin" pointcut-ref="pointcut"/>
            <!--后置通知-->
            <aop:after method="close" pointcut-ref="pointcut"/>
            <!--异常通知-->
            <aop:after-throwing method="rollback" throwing="e" pointcut-ref="pointcut"/>
            <!--最终通知-->
            <aop:after-returning method="commit" pointcut-ref="pointcut"/>
            
             <!--环绕通知  用这个上面就可以全部注释不用了 -->
            <aop:around method="around" pointcut-ref="pointcut"/>

        </aop:aspect>

    </aop:config>
    <bean id="txmanager" class="cn.itsource._04_xmlaop.TxManager"></bean>
</beans>

TxManager 类 类名方法名按照要求

public class TxManager {
    public void begin(){
        System.out.println("开启事务");
    }


    public void commit(){
        System.out.println("提交事务");
    }

    //Throwable 异常对象 所有Exception的父类
    public  void rollback(Throwable e){
        System.out.println("回滚事务"+e.getMessage());
    }

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

    public void around (ProceedingJoinPoint joinPoint){
            String name = joinPoint.getSignature().getName();
        try {
            if ("find".equals(name)||"query".equals(name)){
                joinPoint.proceed();
            }else {
                begin();
                System.out.println(name);
                commit();
            }
        }catch(Throwable e ){
            e.getStackTrace();
            rollback(e);
        }finally {
            close();
        }
    }
}

AOP一些基本 单词
连接点(Joinpoint):程序执行的某一个特定位置,如类初始前后,方法的运行前后。而Spring只支持方法的连接点。
切点(Pointcut):切点可以定位到相应的连接点,一个切点可以定位多个连接点。
增强(Advice):又被称为通知,完成逻辑的增强。
目标对象(Target):增强逻辑织入的目标类。
引介(Introduction):特殊的增强,为类添加一些属性和方法。
织入(Weaving): 将增强添加到目标类的具体连接点上的过程。Spring使用动态代理织入。
代理(Proxy):一个类(原类)被织入增强(逻辑)后,就产生一个结果类,称为代理类。
切面(Aspect):由切点和增强组成

2.2 注解版的aop
配置

   <!-- 开启扫描 controller service repository component-->
    <context:component-scan base-package="cn.itsource._05_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("关闭资源....");
	}
}

如果用环绕通知 就不要把上面的方法打上注解 会重复

//环绕通知
    @Around("pointcut()")
    public void around(ProceedingJoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        try {
            if("find".equals(methodName) || "query".equals(methodName)){
                joinPoint.proceed();//去执行方法 save
            }else {
                begin();
                System.out.println(joinPoint.getSignature().getName());
                joinPoint.proceed();//去执行方法 save
                commit();
            }
        } catch (Throwable e) {
            e.printStackTrace();
            rollback(e);
        }finally {
            if("find".equals(methodName) || "query".equals(methodName)) {

            }else{
                close();
            }
        }

    }

小结:
AOP是面向切面编程,是对咱们OOP的一个补充,Spring的Aop允许咱们在方法的前后加上相应的功能增强。
Spring的Aop是使用代理模式完成的,如果是有接口的类,使用JDK代理模式,如果没有接口的类,使用CGLIB代理模式。
咱们自己使用AOP太麻烦,Spring让我们通过简单的配置即可完成AOP。
第一种配置:XML 第二种配置:注解
配置的时候注意找到何时(方法前后,异常),何地(哪些类的哪些方法),做什么(安全中是添加事务

相关标签: SpringAOP