Spring(二) Spring中的AOP和属性注入

一.AOP(Aspect Oriented Programing)面向切面编程

AOP的终极目标:让我们可以专心做事

下面通过一个例子来介绍AOP的具体使用

案例的要求:使用AOP实现日志记录系统 ,  核心模块  和    增强  单独  开发  ,运行时再组装

首先定义接口和方法

接口和实现类中的代码,我放在一起了,应该比较简单

package demo04.dao;

/**
 * Created by mycom on 2018/3/5.
 */
public interface IHelloDao {
    public void doSome();
}
package demo04.dao;

/** * Created by mycom on 2018/3/5. */public class HelloDaoImpl implements IHelloDao {    public void doSome() {        System.out.println("已经成功加入到DB中了");    }}

package demo04.service;

/** * Created by mycom on 2018/3/5. */public interface IHelloService {    public void doSome();}
package demo04.service;

import demo04.dao.IHelloDao;

/** * Created by mycom on 2018/3/5. */public class HelloServiceImpl implements IHelloService {    //创建一个Dao的对象    IHelloDao dao;

public IHelloDao getDao() {        return dao;    }

public void setDao(IHelloDao dao) {        this.dao = dao;    }

public void doSome() {        dao.doSome();    }}

同样在resources下面也要有一个xml文件----applicationContext.xml

<!--返回的类型只能是实现类-->  这里需要注意一下  class的值只能是实现类的包
    <bean id="dao" class="demo04.dao.HelloDaoImpl">
    </bean>

    <bean id="service" class="demo04.service.HelloServiceImpl">
        <property name="dao" ref="dao"></property>
    </bean>

然后编写测试类进行测试

@Test
    public void t1(){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContextAop.xml");
        //这里的返回值只能是接口
        IHelloService service =(IHelloService) context.getBean("service");
        service.doSome();
    }

运行的结果

现在我们要在这句话出现之前,先记录一下日志,出现之后,再出现一句话

首先要创建一个新的包AOP包,并且在包下面写两个类

LoggerAfter是后置增强

LoggerBefore是前置增强

这两个类中的代码如下

package demo04.aop;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

/**
 * Created by mycom on 2018/3/5.
 */
public class LoggerAfter implements AfterReturningAdvice {
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("=======after");
    }
}
package demo04.aop;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

/**
 * Created by mycom on 2018/3/5.
 */
public class LoggerBefore implements MethodBeforeAdvice {
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("日志记录");
    }
}

在xml中配置,在配置xml是要给AOP添加一个约束

<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="service" class="demo04.service.HelloServiceImpl">
        <property name="dao" ref="dao"></property>
    </bean>
    <!--前置-->
    <bean id="beforeAdvice" class="demo04.aop.LoggerBefore">
    </bean>
    <!--后置-->
    <bean id="afterAdvice" class="demo04.aop.LoggerAfter">
    </bean>
    <!--配置aop-->
    <aop:config>
        <!--切点-->
        <aop:pointcut id="mypoint" expression="execution(public void demo04.service.HelloServiceImpl.doSome())"></aop:pointcut>
        <!--<aop:pointcut id="mypoint" expression="execution(* *..service.*.*(..))"></aop:pointcut>-->
        <!--advice-ref:做什么样的配置,是前置还是后置
        pointcut-ref:锁定什么样的方法规则,那个方法需要被锁定
        -->
        <aop:advisor advice-ref="beforeAdvice" pointcut-ref="mypoint"></aop:advisor>
        <aop:advisor advice-ref="afterAdvice" pointcut-ref="mypoint"></aop:advisor>
    </aop:config>

测试类

import demo04.service.HelloServiceImpl;
import demo04.service.IHelloService;
import demo05.MyCollection;
import demo05.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by mycom on 2018/3/3.
 */
public class Test20180305 {
    @Test
    public void t1(){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContextAop.xml");
        //这里的返回值只能是接口
        IHelloService service =(IHelloService) context.getBean("service");
        service.doSome();

    }

}

在这里和要介绍两个单词的意思

advice :通知
advisor:顾问

顾问可以包装通知
execution(【modifiers-pattern?】 访问修饰符
ret-type-pattern 返回值类型
【declaring-type-pattern?】 全限定性类名
name-pattern(param-pattern) 方法名(参数名) 包名.类型名.方法名
【throws-pattern?】) 抛出异常类型
public void doLog(String log){

}
方法签名
切入点表达式要匹配的对象就是目标方法的方法名。所以,execution表达式中明显就是方法的签名。
注意:表达式中加[]的部分表示可省略部分,各部分间用空格分开。在其中可以使用以下符号:
符号 意义
* 0至多个任意字符
.. 用在方法参数中,表示任意多个参数
用在包名后,表示当前包及其子包路径
+ 用在类名后,表示当前类及其子类
用在接口后,表示当前接口及其实现类
案例:
execution(public * *(..)) 指定切入点为:任意公共方法
execution(* set*(..)) 指定切入点为:任何一个以"set"开始的方法

二.给属性注入值(四种)

1.setter方法注入(就是在bean节点下有property节点给里面的属性值赋值

<bean id="service" class="demo04.service.HelloServiceImpl">
        <property name="dao" ref="dao"></property>
    </bean>

2.构造注入

3.p命名空间注入(使用前要先要在Spring配置文件中引入p命名空间xmlns:p="http://www.springframework.org/schema/p")

这里的两种我写在一起了

首先写一个学生类,车类,MyCollection

package demo05;

/**
 * Created by mycom on 2018/3/5.
 */
public class Student {
    private String name;
    private Integer age;
    private Car car;

    public Student() {
    }

    public Student(String name, Integer age) {

        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }
}
package demo05;

/**
 * Created by mycom on 2018/3/5.
 */
public class Car {
    private String color;
    private String brand;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getColor() {

        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}

在xml中的配置

<!--构造注入-->
    <!--<bean id="stu" class="demo05.Student">
        <constructor-arg index="0" value="小明"></constructor-arg>
        <constructor-arg index="1" value="12"></constructor-arg>
    </bean>-->
    <!--p命名空间注入-->
    <bean id="stu" class="demo05.Student" p:name="小明" p:age="12" p:car-ref="car"></bean>

最后编写测试类

以p命名空间注入为例进行测试

import demo04.service.HelloServiceImpl;
import demo04.service.IHelloService;
import demo05.MyCollection;
import demo05.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by mycom on 2018/3/3.
 */
public class Test20180305 {
    @Test
    public void t1(){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContextCon.xml");
Student service2 =(Student) context.getBean("stu");System.out.println(service2.getName());
 } }

4.集合注入

再写一个MyCollection类

package demo05;

import java.util.*;

/**
 * Created by mycom on 2018/3/5.
 */
public class MyCollection {
    private String[] array;
    private List<String> list;
    private Set<String> set;
    private Map<String,String> map;
    private Properties properties;

    public MyCollection() {
        System.out.println("创建对象===========");
    }

    public MyCollection(String[] array, List<String> list, Set<String> set, Map<String, String> map, Properties properties) {
        this.array = array;
        this.list = list;
        this.set = set;
        this.map = map;
        this.properties = properties;
    }

   @Override
    public String toString() {
        return "MyCollection{" +
                "array=" + Arrays.toString(array) +
                ", list=" + list +
                ", set=" + set +
                ", map=" + map +
                ", properties=" + properties +
                ‘}‘;
    }

    public String[] getArray() {
        return array;
    }

    public void setArray(String[] array) {
        this.array = array;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public Set<String> getSet() {
        return set;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public Map<String, String> getMap() {
        return map;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}
<!--集合注入-->
    <bean id="collection" class="demo05.MyCollection" scope="prototype">
        <!--Array-->
        <property name="array">
            <array>
                <value>小明</value>
                <value>小兰</value>
            </array>
        </property>
        <!--list-->
        <property name="list">
            <list>
                <value>list1</value>
                <value>list2</value>
            </list>
        </property>
        <!--set-->
        <property name="set">
            <set>
                <value>set1</value>
                <value>set2</value>
            </set>
        </property>
        <!--map-->
        <property name="map">
            <map>
                <entry key="1">
                    <value>01</value>
                </entry>
                <entry key="2">
                    <value>02</value>
                </entry>
            </map>
        </property>
        <!--propreties-->
        <property name="properties">
            <props>
                <prop key="001">001</prop>
                <prop key="002">002</prop>
            </props>
        </property>
    </bean>
import demo04.service.HelloServiceImpl;
import demo04.service.IHelloService;
import demo05.MyCollection;
import demo05.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by mycom on 2018/3/3.
 */
public class Test20180305 {
    @Test
    public void t1(){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContextCon.xml");
       //返回的类型只能是接口
        MyCollection service =(MyCollection) context.getBean("collection");
        System.out.println(service);
       }

}

三.Spring中bean是单例的问题

单例:一个类在内存中只能有一个对象。

单利满足的三个条件:

1.构造私有

2.是有的静态变量,变量的类型就是当前类的类型

3.提供一个静态方法

在xml中配置实现单例还是多例的属性是scope

他的值有两个singleton  单例

      prototype 多例

在上面的集合注入的例子中进行改动,并且如果MyCollection中有toString方法,也要注释掉,可以更直观的看到,如下

然后我们来编写测试方法进行测试

import demo04.service.HelloServiceImpl;
import demo04.service.IHelloService;
import demo05.MyCollection;
import demo05.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by mycom on 2018/3/3.
 */
public class Test20180305 {
    @Test
    public void t1(){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContextCon.xml");

        MyCollection service =(MyCollection) context.getBean("collection");
        System.out.println(service);
        MyCollection service2 =(MyCollection) context.getBean("collection");
        System.out.println(service2);

    }

}

运行结果

从运行结果来看,两次创建的对象的指针不同,创建的是两个对象,这是多例

线面再来看单例,将scope的属性值改为singleton

此时的运行结果如下

他只创建了依次对象,实现了单利

原文地址:https://www.cnblogs.com/my-123/p/8511620.html

时间: 2024-10-21 11:56:23

Spring(二) Spring中的AOP和属性注入的相关文章

spring 基本操作总结主要是aop以及依赖注入的基本配置

一所需架包 spring commom-logging.jar  spring.jar 注解 common-annotation.jar aop面向切面 aspectjrt.jar    aspectjweaver.jar  cglibb-nodep.ja(权限带代理proxy) jdbc database common-pool.1.6.jar common-dbhp.jar mysql-connector-bin-*.*.*.jar 二 配置文件的模板beans.xml <?xml vers

spring-boot实战【05】:Spring Boo多环境配置及配置属性注入到对象

项目工程结构: 配置文件application.properties文件 com.yucong.blog.name=yucong com.yucong.blog.title=Spring Boot Course com.yucong.blog.desc=${com.yucong.blog.name} is learing ${com.yucong.blog.title} # 随机字符串 com.yucong.blog.value=${random.value} # 随机int com.yucon

spring自定义类中@AutoWired标识的元素注入为null

最近在做项目的时候,发现程序运行的时候有一个nullpointer exception,一脸懵逼因为感觉程序没什么逻辑.后来发现是因为new出来的component不会自动注入它的元素. 现象:@Component修饰的自定义普通类中@Autowired属性为null 原因:如果是通过new实例化的对象,脱离了Spring的管理,所以获取不到Spring注解的属性值. 在新线程中也会存在注解获取不到Spring管理的Bean,也是因为new出来的线程,脱离了Spring容器 我在实际开发中遇到有

在netcore中实现字段和属性注入

简单来说,使用Ioc模式需要两个步骤,第一是把服务注册到容器中,第二是从容器中获取服务,我们一个一个讨论并演化.这里不会考虑使用如Autofac等第三方的容器来代替默认容器,只是提供一些简单实用的小方法用于简化应用层的开发. 将服务注入到容器 asp.netcore官方给出的在容器中注册服务方法是,要在Startup类的ConfigureServices方法中添加服务,如下所示: public void ConfigureServices(IServiceCollection services)

ASP.NET Core中使用Autofac进行属性注入

一些无关紧要的废话: 作为一名双修程序员(自封的),喜欢那种使用Spring的注解形式进行依赖注入或者Unity的特性形式进行依赖注入,当然,形式大同小异,但结果都是一样的,通过属性进行依赖注入. ASP.NET Core中使用了自带的Dependency Injection作为了默认的IOC容器,当然有先天的优势,很多还是喜欢切换到Autofac作为IOC容器,Unity在.Net Core中还是有很大的优势的,但据我所知,Unity5已经由微软转交到基金会了,而且本身文档很少,翻译文档以及研

Spring(二)Spring对JavaBean的管理

部分与第一篇重复的内容省掉了. 用实体类保存JavaBean的配置信息 package test.spring.entity; public class Bean { private String id; private String classPath; public Bean(String id, String classPath) { super(); this.id = id; this.classPath = classPath; } public String getId() { r

框架学习之Spring(二)----AOP and jdbcTemplate

一.AOP aop底层使用动态代理实现 (1)第一种情况,有接口情况,使用动态代理创建接口实现类代理对象 (2)第二种情况,没有接口情况,使用动态代理创建类的子类代理对象 图解:1> 2> 二.AOP操作术语 Joinpoint(连接点):类里面可以被增强的方法,这些方法称为连接点. Pointcut(切入点):所谓切入点是指我们要对那些Joinpoint进行拦截的定义. Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知,通知分为前置通知,后置通知,异常

Spring中的AOP注解方式和配置方式

今天学习了下spring中的切面编程:结合之前看过的视频.整合一下思路: 基本类: 接口: public interface ArithmeticCalculator { int add(int i, int j); int sub(int i, int j); int mul(int i, int j); int div(int i, int j); } 接口的实现: import org.springframework.stereotype.Component; @Component("ar

Spring 在XML中声明切面/AOP

在Spring的AOP配置命名空间中,我们能够找到声明式切面选择.看以下: <aop:config> <!-- AOP定义開始 --> <aop:pointcut/> <!-- 定义切入点 --> <aop:advisor/> <!-- 定义AOP通知器 --> <aop:aspect> <!-- 定义切面開始 --> <aop:pointcut/> <!-- 定义切入点 --> <