AOP

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

依赖注入;(掌握)

什么是依赖注入?(DI),是Spring里面的特性

​ 依赖注入就是一个类里面依赖于另外一个类,然后Spring把类的对象创建出来,然后再注入到相应的类里面,这个过程就叫做依赖注入。

依赖注入的方式:

​ 1. Set方法注入

​ 2. 构造器注入

​ 3. 注解方式注入

要使用依赖注入就要先配置环境导包:
//导包
<?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>


property:属性注入的意思
//普通方式注入  相当于就是调用了Set直接赋值
<property name = "id" value="1"> </property>  //property:属性注入的意思


//数组方式注入
<property name = "arrays" > 
    <array>
		<value>'数组方式注入'</value>
		<value>'数组方式注入'</value>
		<value>'数组方式注入'</value>
	</array>
</property> 

//List注入 
<property name = "list" > 
    <list>
		<value>'数组方式注入'</value>
		<value>'数组方式注入'</value>
		<value>'数组方式注入'</value>
	</list>
</property> 

//List  存放对象  引用对象
<property name = "otherBeanList" > 
    <list>
		<bean class="cn.itsource._01_di.OtherBean">'list存放对象'</bean>
		<bean class="cn.itsource._01_di.OtherBean">'list存放对象'</bean>
		<bean class="cn.itsource._01_di.OtherBean">'list存放对象'</bean>
		  //注意: 不引用外部Bean对象是不相同的
            
		<ref bean="otherBean"> '引用外部bean' </ref> 
		<ref bean="otherBean"> '引用外部bean' </ref> 
		
            //注意: 引用外部bean是一样的对象 
            //set 和list的写法是一样的
	</list>
</property> 

//Map注入
<property name = "map" > 
    <map>
		<entry key="key1" value="迪迪">'map方式注入'</entry>
		<entry key="key2" value="强强">'map方式注入'</entry>
		<entry key="key3" value="yyk">'map方式注入'</entry>
	</map>
</property> 

// properties 方式注入   掌握
 private properties p1;
 private properties p2;
// properties 方式一
<property name = "p1" > 
    <props>
		<entry key="key1"> "方式一value值写在这个位置,支持中文"</entry>
		<entry key="key2" >"方式一value值写在这个位置,支持中文"</entry>
		<entry key="key3" >"方式一value值写在这个位置,支持中文"/entry>
	</props>
</property> 
// properties文件是键值对方式的
//作比较   
//properties方式二
<property name = "p2" > 
    <props>
		<prop key="key1" ></prop>
		<prop key="key2" ></prop>
		<prop key="key3" ></prop>
	</props>
</property> 
<property name = "p2" > 
    <value>
		key1="方式二是这样注入值 且不支持中文版"
         key2="方式二是这样注入值 且不支持中文版"
         key3="方式二是这样注入值 且不支持中文版"
	</value>
</property> 


XML自动注入;(了解)

使用XML自动注入,可以简化我们XML的配置。

不过对于学习阶段,并不建议大家这样来使用。

简化spring的配置文件

byName 按照属性的名称 setXxx方法

	bean.id的名称

byType 按照注入对象的类型,要求:类型只能配置一个实例

​ setXxx方法 注入类的类型(Class)

​ 和配置文件里面的类型进行比较

​ 配置文件里面的类型只能是1个

配置方案

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

子节点bean autowire="byType"只对当前bean生效

<bean id="userDao" class="cn.itsource._02_.UserDaoImpl"></bean> <bean id="userService" class="cn.itsource._02_.UserServiceImpl"></bean> <bean id="userServicex" class="cn.itsource._02_.UserServiceImpl"></bean> <bean id="userController" class="cn.itsource._02_.UserController" autowire="byName"></bean>
default-autowire="byName"  //通过名字注入
default-autowire="ByType"  //通过类型注入

全注解注入配置;(重点掌握)

1.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">


//第一步:配置让Spring扫描类与支持注解
/*
	@Component  普通仓库
	@Repository  仓库(其实就是dao层)
	@Service	service层
	@Controller  控制层(servlet、action)
*/
//进行包的扫描,去看类上面是否有相应的标签配置
<context:component-scan base-package="cn.itsource._03_anno" />
//这个不是必须的(spring3.2版本前使用) 配上后兼容性好
<context:annotation-config />

@Scope(“prototype”)//默认产生单例  这是配置多例
注解配置bean的名称
//接口有两个实现(可能性比较少)
完成之后,大家注意,现在的配置还有一个问题,比如说我按真实情况来一个Dao接口,然后这个接口有两个实现,现在就会出问题
IUserDao  (UserJdbcDaoImpl/UserJpaDaoImpl)
而我们声明的时候就是使用了IUserDao
@Service
public class UserService {
	@Autowired
	private IUserDao userDao;
	public void save(){
		userDao.save();
	}
}
//此时会就出错:因为Spring不知道你用的是哪一个dao的实现
//解决的方案:为dao生成的bean加上名称,我们在调用的时候确定名称即可。
@Repository("userJdbcDao")
public class UserJdbcDaoImpl  implements IUserDao{
	public void save(){
		System.out.println("保存数据xxxx....");
	}
}
@Repository("userJpaDao")
public class UserJpaDaoImpl  implements IUserDao{
	public void save(){
		System.out.println("保存数据xxxx....");
	}
}

//调用名称两套方案:

//方案一:使用@Autowired
@Service
public class UserService {
	@Autowired
	@Qualifier("userJdbcDao")
	private IUserDao userDao;
	public void save(){
		userDao.save();
	}
}

//方案二:使用@Resource
@Service
public class UserService {
	@Resource(name="userJpaDao")
	private IUserDao userDao;
	public void save(){
		userDao.save();
	}
}

那么,使用哪一种方法更好呢? 使用AutoWired;

AutoWired和Resource有什么区别? 面试题

byName 根据名字 byType 根据类型

  1. autowired 和 resource 都可以注入对象;
  2. autowired是Spring里面提供的注解,resource是java原生支持的注解
  3. autowired可以和Spring进行无缝的衔接(效率更好)
  4. autowired默认根据类型进行配置,如果匹配不是,就根据name进行匹配
  5. resourc是先根据名字匹配,匹配不上再根据类型进行匹配
  6. 建议使用AutoWired这个注解

AOP;(掌握)

​ AOP他也是Spring一个特性,面向切面的编程

什么叫面向切面编程?(AOP)

​ 他的产生并不是取代面向对象,而是对面向对象进行扩展,可以按照一定的方式,把类切开(切到方法上面),可以往方法前后添加一些逻辑

什么叫面向对象编程? (OOP)

​ 用一个实实在在在的个体去操作数据,我们在写程序,可以把上面内容都看成对象,使用对象思想进行编程

​ AOP使用场景

事务管理  日志管理   性能监控    拦截器
AOP实现

低耦合/松耦合: 类和类之间的链接程度很低

底层是通过代理模式实现 — 代理模式 JDK/CGLIB动态代理

JDK:针对有接口情况下使用的代理模式 – 优先推从

CGLIB:没有接口的情况下使用的代理模式 — 不能定义为 final修饰类

Xml版实现AOP

// 配置 添加aop命名空间
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd


//前置增强(通知)
<aop:config>
	<!--pointcut 切点  (* cn.itsource.aop.I*Service.*(..)) 代表所有下面的指定的包下面所有的 I开头的所有的* Service 接口上面方法前面       -->
	<aop:pointcut expression="execution(* cn.itsource.aop.I*Service.*(..))" id="pointcut" />
     <!-- asoect 方面或者切面 -->
	<aop:aspect  ref="txManager">
		<!-- 前置通知 -->
		<aop:before method="begin" pointcut-ref="pointcut"/>
		<!-- 后置通知 -->
		<aop:after-returning method="commit" pointcut-ref="pointcut"/>
		<!-- 异常通知 -->
		<aop:after-throwing method="rollback" throwing="e" pointcut-ref="pointcut"/>
		<!-- 最终通知 -->
		<aop:after method="close" pointcut-ref="pointcut" />
	</aop:aspect>
	<bean id="txManager" calss=" cn.…………………………"></bean>
</aop:config>

//=========================================分割线==========================================

//环绕增强(前面的4个增强就不用了)
<!-- 
	环绕通知:有了环绕,就不需要用另外几个通知(会重复)
		       如果有两个以上的通知,建议使用环绕
 -->
<aop:around method="around" pointcut-ref="pointcut" />

    
 //环绕通知需要写一个环绕方法
import org.aspectj.lang.ProceedingJoinPoint;
public Object around(ProceedingJoinPoint joinPoint){
	Object object = null;
	try {
		begin();
		object = joinPoint.proceed(); //执行相应的代码
		commit();
	} catch (Throwable e) {
		rollback(e);
	}finally{
		close();
	}
	return object;
}


注解版本实现AOP

//配置文件
<!-- 开启扫描 -->
<context:component-scan base-package="cn.itsource.包名" />
<!-- 支持aop注解支持 -->
<aop:aspectj-autoproxy />

//在类上面配置这两个注解  
@Component  //让Soring扫描到该类
@Aspect //AOP的增强类注解 把该类的功能添加到业务上去
    
//然后再方法上面配置
//设置切点
@Pointcut("execution(* cn.itsource.包名.I*Service.*(..))")
public void pointcut(){}

//再配置前置通知   这样可控性比较低  最好还是使用环绕通知
//前置通知
@Before("pointcut()") //@Before 前置通知注解
public void begin(){
	System.out.println("开启事务....");
} 

//======================================分割线======================================

//环绕通知方法:
//温馨提醒:如果要使用环绕通知的话,把其它几个通知的注解去掉(不然会出现重复)
@Around("pointcut()") //环绕通知注解 Around
public Object around(ProceedingJoinPoint joinPoint){
	Object object = null;
	try {
		begin();
		object = joinPoint.proceed(); //执行相应的代码
		commit();
	} catch (Throwable e) {
		rollback(e);
	}finally{
		close();
	}
	return object;
}


    

代理模式;(掌握,超难)

单例模式

工厂模式

装饰者模式

适配器模式

代理模式: proxy

代理模式分类:

​ 静态代理模式: 缺点 如果对多个接口或者多个方法,写很多额外的代理实现
​ 动态代理模式 — JDK(有接口的代理)/CGLIB(没有接口的代理)


开发专业术语:

抽象主题角色

代理主题角色

真实主题角色

Bean的创建方式(掌握)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值