使用注解開發
- 類的注入
@Component //等價于<bean id="user" class="com.lyc.pojo.User"/>
//元件,放在類上,說明這個類被Spring管理了
<!--指定要掃描的包,包下的注解就會生效-->
<context:component-scan base-package="com.lyc.pojo"/>
-
屬性的注入
放在屬性上方
@value
@Value("lyc") private String name; //等價于 <property name>
- @Component會按照mvc三層架構分層,實質上都是元件的裝配
- dao @Repository
- service @Service
- controller @Controller
@Scope("singleton") //配置bean的作用域,聲明這個類為單例模式
//等價于 bean scope标簽
xml配置複雜的東西,注解适用于配置簡單的東西
使用JavaConfig配置spring
不使用xml去配置
Javaconfig注冊類到Spring
@Configuration
public class UserConfig {
@Bean
public User getUser(){
return new User();
}
}
測試類
@Test
public void test2(){
ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);
User user = (User) context.getBean("getUser");
System.out.println(user.getName());
}
}
代理模式
分類
- 靜态代理
- 動态代理
靜态代理
- 抽象角色:一般使用接口或者抽象類
- 真實角色:被代理的角色
- 代理角色:代理真實角色,有一些附屬操作
- 客戶:真實使用資源的人
例子
接口
public interface Rent {
public void rent();
}
真實角色
public class Host implements Rent{
public void rent() {
System.out.println("租房成功");
}
}
代理角色
public class Proxy implements Rent{
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
public void rent() {
host.rent();
}
}
客戶
public class Client {
public static void main(String[] args) {
Host host = new Host();
Proxy proxy = new Proxy(host);
proxy.rent(); //客戶直接面對的是proxy
}
}
好處
- 使得真實角色的操作更加純粹,不用去關注一些公共的業務
- 公共業務交給代理角色
- 公共業務發生擴充的時候,友善集中管理
靜态代理缺點
- 一個真實角色會産生一個代理角色,代碼量會上去
動态代理
使用反射動态加載類,減少代碼量
- 抽象角色:一般使用接口或者抽象類
- 真實角色:被代理的角色
- 代理角色:代理真實角色,有一些附屬操作,動态生成代理類
- 客戶:真實使用資源的人
動态分類
- 基于接口的動态代理
- 基于類的動态代理
Proxy:代理
InvocationHandler:産生代理類
萬能工具類
//自動生産動态類
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Object target;
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
//生成得到代理類
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//處理代理執行個體,并傳回結果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
Object result = method.invoke(target, args);
return result;
}
public void seeHouse(){
System.out.println("看房子");
}
}
通過傳入對象不同,來分别加載對應的類,産生對應的代理類!
一個動态代理類代理一個接口
AOP
面向切面程式設計,通過預編譯方式和運作期動态代理程式功能的統一維護的一種技術
在Spring中AOP
提供聲明式事務;允許使用者自定義切面
- 橫切關注點:跨越應用程式多個子產品的方法或功能。即是與我們業務邏輯無關的,但是我們需要關注的部分,就是橫切關注點,如日志,安全,緩存,事務等等
- 切面(Aspect):橫切關注點被子產品化的特殊對象,比如日志類
- 通知(Adivice):切面必須要完成的工作,他是切面類中的一個方法,比如日志類中的方法
- 目标(Target):被通知對象。一個接口或一個方法
- 代理(Proxy):向目标對象應用通知之後建立的對象。比如生成的代理類
- 切入點(PointCut):切面通知執行的地點的定義,比如invoke方法
- 連接配接點(JointPoint):與切入點比對的執行點
Spring5種類型的通知
使用Spring原生api接口實作aop
一添加配置
<!--使用原生API接口-->
<!--配置aop:需要導入aop限制-->
<aop:config>
<!--切入點 expression:表達式,execution(要執行的位置!)-->
<!--限定符,類名,類下面的方法名,參數-->
<aop:pointcut id="pointcut" expression="execution(public * com.lyc.service.UserServiceImpl.* (..))"/>
<!--執行環繞-->
<aop:advisor advice-ref="log" pointcut="pointcut" />
<aop:advisor advice-ref="afterLog" pointcut="pointcut" />
</aop:config>
Userservice接口
public interface UserService {
void add();
void delete();
void update();
void select();
}
接口實作類
@Component
public class UserServiceImpl implements UserService{
public void add() {
System.out.println("增加了一個使用者");
}
public void delete() {
System.out.println("删除了一個使用者");
}
public void update() {
System.out.println("修改了一個使用者");
}
public void select() {
System.out.println("查詢了一個使用者");
}
}
前置類型操作
@Component
public class Log implements MethodBeforeAdvice {
/**
* method:要執行的目标對象的方法
* args:參數
* target:目标對象
*/
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName());
}
}
後置傳回操作
@Component
public class AfterLog implements AfterReturningAdvice {
// o:傳回值 objects:參數 o1:目标對象
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println(method.getName()+"傳回結果為"+o);
}
}
測試類
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService userservice = (UserService) context.getBean("userServiceImpl"); //代理接口,但要獲得接口實作類的bean
userservice.add();
}
}
使用自定義類去實作aop
配置檔案
<!--方式二:自定義類-->
<aop:config>
<aop:aspect ref="diyPointCut">
<aop:pointcut id="pointcut" expression="execution(* com.lyc.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
自定義類
@Component
public class DiyPointCut {
public void before(){
System.out.println("方法執行前");
}
public void after(){
System.out.println("方法執行後");
}
}
注解實作AOP
配置檔案
切面類
//使用注解方式實作AOP
@Component
@Aspect
public class AnnotationPointCut {
@Before("execution(* com.lyc.service.UserServiceImpl.*(..))") //定義切入點
public void before(){
System.out.println("方法執行前");
}
}
void after(){
System.out.println("方法執行後");
}
}
注解實作AOP
配置檔案
切面類
//使用注解方式實作AOP
@Component
@Aspect
public class AnnotationPointCut {
@Before("execution(* com.lyc.service.UserServiceImpl.*(..))") //定義切入點
public void before(){
System.out.println("方法執行前");
}
}